http://www.cnblogs.com/Kymo/archive/2008/05/14/1194161.html

先看一下SQL Server Online Help相关的说明

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

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

 1--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 TESTTRAN;
 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)

SQL Server——事务嵌套(未完工)的更多相关文章

  1. SQL Server 事务嵌套

    示例代码: DECLARE @TranCounter INT; SET @TranCounter = @@TRANCOUNT; -- Procedure called when there is -- ...

  2. 人人都是 DBA(VI)SQL Server 事务日志

    SQL Server 的数据库引擎通过事务服务(Transaction Services)提供事务的 ACID 属性支持.ACID 属性包括: 原子性(Atomicity) 一致性(Consisten ...

  3. SQL Server事务的隔离级别

    SQL Server事务的隔离级别 ########## 数据库中数据的一致性 ########## 针对并发事务出现的数据不一致性,提出了4个级别的解决方法:  隔离级别  第一类丢失更新  脏读 ...

  4. Sql Server 事务隔离级别的查看及更改

    根据自身 Sql Server 的情况来自定义 事务隔离级别,将会更加的满足需求,或提升性能.例如,对于逻辑简单的 Sql Server,完全可以使用 read uncommitted 模式,来减少死 ...

  5. 【SqlServer系列】浅谈SQL Server事务与锁(上篇)

    一  概述 在数据库方面,对于非DBA的程序员来说,事务与锁是一大难点,针对该难点,本篇文章视图采用图文的方式来与大家一起探讨. “浅谈SQL Server 事务与锁”这个专题共分两篇,上篇主讲事务及 ...

  6. 理解Sql Server 事务隔离层级(Transaction Isolation Level)

    关于Sql Server 事务隔离级别,百度百科是这样描述的 隔离级别:一个事务必须与由其他事务进行的资源或数据更改相隔离的程度.隔离级别从允许的并发副作用(例如,脏读或虚拟读取)的角度进行描述. 隔 ...

  7. SQL SERVER 事务和锁

    内容皆整理自网络 一.事务 作者:郭无心链接:https://www.zhihu.com/question/31346392/answer/59815366来源:知乎著作权归作者所有.商业转载请联系作 ...

  8. SQL Server 事务复制爬坑记

    SQL Server 复制功能折腾了好几天了,现特将其配置过程以及其间遇到的问题记录下来,以备日后查阅.同时,也让“同道”同学们少走不必要的弯路.如果有不对之处,欢迎大家指正,欢迎沟通交流. 一.复制 ...

  9. 为什么说JAVA中要慎重使用继承 C# 语言历史版本特性(C# 1.0到C# 8.0汇总) SQL Server事务 事务日志 SQL Server 锁详解 软件架构之 23种设计模式 Oracle与Sqlserver:Order by NULL值介绍 asp.net MVC漏油配置总结

    为什么说JAVA中要慎重使用继承   这篇文章的主题并非鼓励不使用继承,而是仅从使用继承带来的问题出发,讨论继承机制不太好的地方,从而在使用时慎重选择,避开可能遇到的坑. JAVA中使用到继承就会有两 ...

随机推荐

  1. Spring初学之annotation实现AOP前置通知和后置通知

    实现两个整数的加减乘除,并在每个计算前后打印出日志. ArithmeticCalculator.java: package spring.aop.impl; public interface Arit ...

  2. print webpage

    使用浏览器打印网页时(A4纸)有一个固定的尺寸: 高级浏览器: width:700px height:1000px

  3. setintervalue传参数的三种方法

    http://www.cnblogs.com/wkylin/archive/2012/09/07/2674911.html http://www.bhcode.net/article/20110822 ...

  4. nginx路由重定向

    location / { if ($http_host !~ "m.xxx.cn"){ rewrite ^/web/(.*)/bdu(\d?)\.htm(.*)$ /rewrite ...

  5. java: scanner(输入流)文本扫描类

    //scanner是接受system.in输入流的操作类 //scanner同时也支持文件输入流的操作 //一个可以使用正则表达式来分析基本类型和字符串的简单文本扫描器 Scanner scan = ...

  6. Wannafly挑战赛4 B,小AA的数列

    题意:求子区间异或和,要求区间长度在l到r之间,并且为偶数 题解:对于每一位算贡献,可以分奇偶来记录,计算的时候只加上奇偶性相同的就保证了为偶数,从大于l的点开始每次++,从大于r的点每次--,记录二 ...

  7. spring boot 基础篇 -- 定时任务

    在日常项目中,常常会碰到定时监控项目中某个业务的变化,下面是spring boot 集成的定时任务具体配置: @Component public class IndexWarningScheduled ...

  8. JVM 知识点总览 - 高级 Java 工程师面试必备

    在江湖中要练就绝世武功必须内外兼备,精妙的招式和深厚的内功,武功的基础是内功.对于武功低(就像江南七怪)的人,招式更重要,因为他们不能靠内功直接去伤人,只能靠招式,利刃上优势来取胜了,但是练到高手之后 ...

  9. poj-1426-Find The Multiple(打表水过)

    思路: 2的最近可以整除的数是10 所以,很关键的一点,只要是偶数,例如: 6:2*3,可以拆分为能够被2整除和能够被3整除的乘积,所以,10*111=1110 144:72*2,8*9*2,2*2* ...

  10. 剑指Offer-翻转单词顺序

    题目描述: 输入一个英文句子,翻转句子中单词的顺序,但单词内字符串的顺序不变.例如输入字符串:"I am a student",则输出"student a am I&qu ...