设为首页 收藏本站
查看: 865|回复: 0

[经验分享] SQL Server嵌套事务探讨

[复制链接]

尚未签到

发表于 2015-6-28 19:48:25 | 显示全部楼层 |阅读模式
  先看一下SQL Server Online Help相关的说明

  • Begin Transaction:标记一个显式本地事务的起始点。BEGIN TRANSACTION 使 @@TRANCOUNT 按 1 递增。
  • Rollback Transaction: 将显式事务或隐性事务回滚到事务的起点或事务内的某个保存点。(嵌套事务时,该语句将所有内层事务回滚到最外面的 BEGIN TRANSACTION 语句。无论在哪种情况下,ROLLBACK TRANSACTION 都将 @@TRANCOUNT 系统函数减小为 0。ROLLBACK TRANSACTION savepoint_name 不减小 @@TRANCOUNT。)
  • Commit Transaction:标志一个成功的隐性事务或显式事务的结束。如果 @@TRANCOUNT 为 1,COMMIT TRANSACTION 使得自从事务开始以来所执行的所有数据修改成为数据库的永久部分,释放事务所占用的资源,并将 @@TRANCOUNT 减少到 0。如果 @@TRANCOUNT 大于 1,则 COMMIT TRANSACTION 使 @@TRANCOUNT 按 1 递减并且事务将保持活动状态。

下面用代码进行解释,代码是根据Online Help Commit Transaction一节的代码修改而成,首先建立一个Table,然后开始三个Trasaction,中间人为触发一些错误,然后观察运行结果。



1 DSC0000.gif --Bad code
2USE NORTHWIND;
3--Create test table
4IF Object_id(N'TestTran',N'U') IS NOT NULL
5  DROP TABLE TESTTRAN;
6
7CREATE TABLE TESTTRAN (
8  COLA INT   PRIMARY KEY,
9  COLB CHAR(3));
10
11--Variable for keeping @@ERROR
12DECLARE  @_Error INT;
13SET @_Error = 0;
14
15--Begin 3 nested transaction
16BEGIN TRANSACTION OUTERTRAN;
17BEGIN TRANSACTION INNER1;
18BEGIN TRANSACTION INNER2;
19
20INSERT INTO TESTTRAN VALUES     (3,'ccc');--Inner2
21
22RAISERROR('Inner2 error', 16, 1)
23IF @@ERROR = 0
24    COMMIT TRANSACTION INNER2;
25ELSE
26    ROLLBACK TRANSACTION ;
27  
28INSERT INTO TESTTRAN VALUES     (2,'bbb');--Inner1
29
30IF @@ERROR = 0
31    COMMIT TRANSACTION INNER1;
32ELSE
33    ROLLBACK TRANSACTION ;
34  
35INSERT INTO TESTTRAN VALUES     (1,'aaa');--OuterTran
36
37--RAISERROR ('OuterTran error',16,1)
38                        
39IF @@ERROR = 0
40    COMMIT TRANSACTION OuterTran;
41ELSE
42    ROLLBACK TRANSACTION;   
43
44SELECT * FROM   TESTTRAN (NOLOCK);
45SELECT @@Trancount;

上述代码当内层事务发生错误时,并不能正常Rollback,因为Rollback把@@Trancount变成了0,所以后面的Commit语句就找不到对应的Transaction了。解决问题的关键就是Rollback时要判断@@Trancount,当@@Trancount等于1时进行Rollback进行回滚,否则执行Commit把@@Trancount-1,同时把@@Error传到外层事务交给外层事务处理。微软的原文是没有问题的,但是这种情况比较简单,我们一眼就能看出哪个是内层事务,哪个是外层事务,一共嵌套了几层,如果是SP调用呢?你不知道你的SP会被谁调用,也不知道会被嵌套几层。
下面看一下怎么处理内层事务的错误(何时Rollback, Commit及错误的传递)



1--Good code
2USE NORTHWIND;
3
4--Create test table
5IF Object_id(N'TestTran',N'U') IS NOT NULL
6  DROP TABLE TE
STTRAN;
7
8CREATE TABLE TESTTRAN (
9  COLA INT   PRIMARY KEY,
10  COLB CHAR(3));
11
12--Variable for keeping @@ERROR
13DECLARE  @_Error INT;
14SET @_Error = 0;
15
16--Begin 3 nested transaction
17BEGIN TRANSACTION OUTERTRAN;
18BEGIN TRANSACTION INNER1;
19BEGIN TRANSACTION INNER2;
20
21INSERT INTO TESTTRAN VALUES     (3,'ccc');--Inner2
22
23--raiserror('Inner2 error', 16, 1)
24SET    @_Error = @@ERROR              
25IF    @_Error = 0
26    COMMIT TRAN INNER2;
27ELSE
28  IF @@TRANCOUNT > 1
29    COMMIT TRANSACTION INNER2;
30  ELSE
31       ROLLBACK TRANSACTION INNER2;
32  
33INSERT INTO TESTTRAN VALUES     (2,'bbb');--Inner1
34
35IF @_Error = 0
36    SET @_Error = @@ERROR               
37IF @_Error = 0
38    COMMIT TRAN INNER1;
39ELSE
40  IF @@TRANCOUNT > 1
41    COMMIT TRANSACTION INNER1;
42  ELSE
43    ROLLBACK TRANSACTION INNER1;
44  
45INSERT INTO TESTTRAN VALUES     (1,'aaa');--OuterTran
46
47RAISERROR ('OuterTran error',16,1)
48
49--    rollback transaction OuterTran
50SET @_Error = @_Error + @@ERROR
51                        
52IF @_Error = 0
53    COMMIT TRAN OUTERTRAN;
54ELSE
55    IF @@TRANCOUNT > 1
56        COMMIT TRANSACTION;
57    ELSE
58        ROLLBACK TRANSACTION OUTERTRAN;   
59
60SELECT * FROM   TESTTRAN (NOLOCK)

考虑到SP的调用,我们开发SP时应该在最后把@@ERROR返回供调用者检查。另外测试注意检查一下@@Trancount,有时结果看似正确,但是如果@@Trancount不等于0,说明我们的代码出了问题。

  

运维网声明 1、欢迎大家加入本站运维交流群:群②:261659950 群⑤:202807635 群⑦870801961 群⑧679858003
2、本站所有主题由该帖子作者发表,该帖子作者与运维网享有帖子相关版权
3、所有作品的著作权均归原作者享有,请您和我们一样尊重他人的著作权等合法权益。如果您对作品感到满意,请购买正版
4、禁止制作、复制、发布和传播具有反动、淫秽、色情、暴力、凶杀等内容的信息,一经发现立即删除。若您因此触犯法律,一切后果自负,我们对此不承担任何责任
5、所有资源均系网友上传或者通过网络收集,我们仅提供一个展示、介绍、观摩学习的平台,我们不对其内容的准确性、可靠性、正当性、安全性、合法性等负责,亦不承担任何法律责任
6、所有作品仅供您个人学习、研究或欣赏,不得用于商业或者其他用途,否则,一切后果均由您自己承担,我们对此不承担任何法律责任
7、如涉及侵犯版权等问题,请您及时通知我们,我们将立即采取措施予以解决
8、联系人Email:admin@iyunv.com 网址:www.yunweiku.com

所有资源均系网友上传或者通过网络收集,我们仅提供一个展示、介绍、观摩学习的平台,我们不对其承担任何法律责任,如涉及侵犯版权等问题,请您及时通知我们,我们将立即处理,联系人Email:kefu@iyunv.com,QQ:1061981298 本贴地址:https://www.yunweiku.com/thread-81336-1-1.html 上篇帖子: 《Microsoft Sql server 2008 Internals》读书笔记--第六章Indexes:Internals and Management(1 下篇帖子: 《Microsoft Sql server 2008 Internals》读书笔记--第三章Databases and Database Files(2)
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

扫码加入运维网微信交流群X

扫码加入运维网微信交流群

扫描二维码加入运维网微信交流群,最新一手资源尽在官方微信交流群!快快加入我们吧...

扫描微信二维码查看详情

客服E-mail:kefu@iyunv.com 客服QQ:1061981298


QQ群⑦:运维网交流群⑦ QQ群⑧:运维网交流群⑧ k8s群:运维网kubernetes交流群


提醒:禁止发布任何违反国家法律、法规的言论与图片等内容;本站内容均来自个人观点与网络等信息,非本站认同之观点.


本站大部分资源是网友从网上搜集分享而来,其版权均归原作者及其网站所有,我们尊重他人的合法权益,如有内容侵犯您的合法权益,请及时与我们联系进行核实删除!



合作伙伴: 青云cloud

快速回复 返回顶部 返回列表