微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

SqlServer嵌套事务机制 测试

sqlServer 事务相关:《嵌套事务(一):.NET中嵌套事务运用的一点思考

         《嵌套事务(二):SqlServer中嵌套事务使用

                       《 SqlServer嵌套事务机制 测试 

今天我们主研究一下sqlServer中嵌套事务使用代码能说明大多数问题,看代码

1.嵌套事务提交原理测试

结果:

Trancount before transaction: 0
After first BEGIN TRAN: 1
After second BEGIN TRAN: 2
After first COMMIT TRAN: 1
After second COMMIT TRAN: 0

我们可以得出:

1.可以看到每一个BEGIN TRAN语句都会使@@TRANCOUNT增加1;

2.每一个COMMIT TRAN语句都会使@@TRANCOUNT减少1;

3.如前所述,一个值为0@@TRANCOUNT意味着没有打开的事务;

4.因此,在@@TRANCOUNT值从1降到0时结束的事务发生在最外层事务提交的时候。

2. 嵌套事务回滚

2.1  嵌套事务回滚最外面事务,对内部事务有什么影响?

我们再来看一段代码

结果:没有数据。

现在看来:无论数据是否提交,只要最外层回滚了就会导致所有内部所有嵌套类回滚。

2.2 嵌套事务回滚内部嵌套事务呢?

再看一段代码

结果:

异常信息


(1 行受影响)
消息 6401,级别 16,状态 1,第 9 行
无法回滚 InProc。找不到该名称的事务或保存点。

(1 行受影响)

(2 行受影响)

我们可以看到:ROLLBACK TRANSACTION InProc 是错误的。原因是没有保存还原点 InProc。代码该改为如下(具体原因请往下看):

 BEGIN TRANSACTION InProc
      save tran InProc;
	  INSERT INTO #TestTrans VALUES (1,'aaaa');
	ROLLBACK TRANSACTION InProc;

操作前保存好回滚点(save tran InProc),回滚时指定当时保存的位置,sqlServer才知道回滚到哪儿去。

3. 事务原理

往下读之前必须了解:全局变量@@trancount 可以确定是否存在打开的事务及其嵌套的深度。

 

提交的事务不能撤销或回滚。

当不存在打开的事务时,@@trancount 等于 0。

执行 begin tran [tranName]语句将 @@trancount 增加 1。

执行commit tran [tranName]语句将 @@trancount 减小 1。

执行 rollback tran  会回滚整个事务并设置@@trancount 为 0。

 

执行 " rollback tran  tranName"语句时有两种情况:

if(tranName 之前 是用 " Save Tran tranName" )  @@trancount值不变

否则,@trancount 减小1

 

具体测试代码

-- 创建临时表
CREATE TABLE #TestTrans(Cola INT PRIMARY KEY,Colb varchar(20) NOT NULL);
               
 select @@TRANCOUNT '未开外部事务';

/* 外部事务 */
BEGIN TRANSACTION OutOfProc;
 select @@TRANCOUNT '开外部事务';
 
--内部事务
    BEGIN TRANSACTION InProc
    
   select @@TRANCOUNT '开内部事务1';

      save tran InProc;
      
       select @@TRANCOUNT '保存内部事务1';
	  INSERT INTO #TestTrans VALUES (1,'aaaa');
	ROLLBACK TRANSACTION InProc;
	
	select @@TRANCOUNT '回滚内部事务1';
	
	--内部事务2
    BEGIN TRANSACTION InProc2
	  INSERT INTO #TestTrans VALUES (2,'222');
	  
	  --内部事务21
	   BEGIN TRANSACTION InProc21
	   select @@TRANCOUNT '开内部事务21';
	     INSERT INTO #TestTrans VALUES (3,'2422');
	     COMMIT TRANSACTION InProc21;
	   select @@TRANCOUNT '提交内部事务21';
	     
	COMMIT TRANSACTION InProc2;
	select @@TRANCOUNT '提交内部事务2';
	
/* 提交外部事务 */
COMMIT TRANSACTION OutOfProc;

select @@TRANCOUNT '提交外部事务';

SELECT * FROM #TestTrans;

drop table #TestTrans

结果:

其他:

保存事务回滚点--可以有选择的提交或回滚内部嵌套事务。

思路

检查@@TRANCOUNT的值,以此来确定是否需要开始一个事务。如果@@TRANCOUNT大于0,则不开启新事务,只需要保存的个回滚位置即可;否则,开启新事务。下面是操作:

 

1.保存回滚点

 declare @trancount int --commit,rollback只控制本存储过程
    set @trancount = @@trancount 
    if (@trancount=0) /*判断事务记数,根据情况确定使用保存点或者新建一个事务*/ 
		begin tran curtran--当前事务点,rollback、commit都从这里开始 
    else
		save tran curtran

2. 回滚指定“回滚点”:

	if(@error <> 0 or @pay_way_error = 0) --@pay_way_error 决定了是否需要回滚
		begin
			rollback tran curtran
			set @result = -1 --异常
		end



	if(@error <> 0 or @pay_way_error = 0) --@pay_way_error 决定了是否需要回滚
		begin
			rollback tran curtran
			set @result = -1 --异常
		end
@H_502_323@

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 [email protected] 举报,一经查实,本站将立刻删除。

相关推荐