2009-11-28 45 views
6

我已阅读了关于ROLLBACK TRANSACTIONnesting transactions的MSDN。虽然我看到ROLLBACK TRANSACTION savepointname的观点,但我不明白ROLLBACK TRANSACTION transactionname“ROLLBACK TRANSACTION named_transaction”的含义是什么?

  1. transactionname是最外面的事务它仅适用
  2. ROLLBACK总是回滚整个事务“栈”,除了在savepointname

的情况下基本上,我阅读文档,除了在保存点的情况下,ROLLBACK回滚所有交易(至@@TRANCOUNT=0)。我能看到的唯一区别是这样的片段:

如果使用的 名称的ROLLBACK TRANSACTION transaction_name语句外交易在一组嵌套 交易的任何级别执行,所有的嵌套事务的被回滚。 如果在一组嵌套的 事务的任何级别上执行不带 transaction_name参数的ROLLBACK WORK或ROLLBACK TRANSACTION语句,它将回滚所有嵌套事务,包括最外层事务 。

从阅读中,这向我建议回滚一个命名事务(它必须是最外层事务的名称),只有嵌套事务将被回滚。这会给回滚一个已命名的事务带来一些意义。所以,我建立了一个试验:

CREATE TABLE #TEMP (id varchar(50)) 

INSERT INTO #TEMP (id) VALUES ('NO') 
SELECT id AS NOTRAN FROM #TEMP 
SELECT @@TRANCOUNT AS NOTRAN_TRANCOUNT 

BEGIN TRAN OUTERTRAN 

INSERT INTO #TEMP (id) VALUES ('OUTER') 
SELECT id AS OUTERTRAN FROM #TEMP 
SELECT @@TRANCOUNT AS OUTERTRAN_TRANCOUNT 

BEGIN TRAN INNERTRAN 

INSERT INTO #TEMP (id) VALUES ('INNER') 
SELECT id AS INNERTRAN FROM #TEMP 
SELECT @@TRANCOUNT AS INNERTRAN_TRANCOUNT 

ROLLBACK TRAN OUTERTRAN 

IF @@TRANCOUNT > 0 ROLLBACK TRAN 

SELECT id AS AFTERROLLBACK FROM #TEMP 
SELECT @@TRANCOUNT AS AFTERROLLBACK_TRANCOUNT 

DROP TABLE #TEMP 

结果(所有“受影响的X行(S)”的东西去掉)

NOTRAN 
-------------------------------------------------- 
NO 

NOTRAN_TRANCOUNT 
---------------- 
0 

OUTERTRAN 
-------------------------------------------------- 
NO 
OUTER 

OUTERTRAN_TRANCOUNT 
------------------- 
1 

INNERTRAN 
-------------------------------------------------- 
NO 
OUTER 
INNER 

INNERTRAN_TRANCOUNT 
------------------- 
2 

AFTERROLLBACK 
-------------------------------------------------- 
NO 

AFTERROLLBACK_TRANCOUNT 
----------------------- 
0 

注意有没有区别当我改变输出

ROLLBACK TRAN OUTERTRAN 

简单

​​

那么ROLLBACK TRANSACTION named_transaction有什么意义?

回答

5

保存点与名称所暗示的完全相同:日志序列中的“保存点”。日志序列总是线性的。如果您回滚到保存点,则回滚所有内容您的交易在当前日志位置和保存点之间进行了操作。考虑你的例子:

LSN 1: BEGIN TRAN OUTERTRAN 
LSN 2: INSERT INTO ... 
LSN 3: BEGIN TRAN INNERTRAN 
LSN 4: INSERT INTO ... 
LSN 5: ROLLBACK TRAN OUTERTRAN 

在日志序列号(LSN)1上创建OUTERTRAN保存点。第一个INSERT创建LSN 2.然后INNERTRAN用LSN创建一个保存点3.第二个INSERT创建一个新的LSN,4. ROLLBACK OUTERTRAN相当于'ROLLBACK日志,直到LSN 1'。您不能'跳过'部分日志,因此您必须回滚日志中的每个操作,直到LSN 1(创建保存点OUTERTRAN时)为止。另一方面,如果在上一次操作中发出ROLLBACK INNERTRAN,则引擎将回退,直到LSN 3('INNERTRAN'保存点插入日志中),从而保留LSN 1和LSN 2(即。第一个INSERT)。

有关保存点的实际示例,请参阅Exception handling and nested transactions

+0

Remus,谢谢。我正在查看你的链接... – 2009-11-28 21:19:40

+0

好吧,我明白你已经做了什么。但是,我仍然对我的原始观点感到好奇。我得到了保存点和它们的价值,但我仍然对回滚事务(不保存点)名称感到困惑。一个重要的说明,显然你不能ROLLBACK一个内部交易。例如ROLLBACK TRAN INNERTRAN导致错误“无法回滚INNERTRAN,没有找到该名称的事务或保存点”。这一点(关于回滚命名嵌套事务被禁止)在我在OP中提到的文档链接中。 – 2009-11-28 21:28:55

+3

'要回滚到INNERTRAN,您需要使用语法'SAVE TRANSACTION INNERTRAN'来创建一个真正的保存点(而不是命名事务)。命名事务主要用于恢复场景('RESTORE WITH STOPAT OUTERTRAN') – 2009-11-28 21:32:18