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. Java -- 利用反射 操作任意数组,包括对象数组 和 基本数据类型的数组

    items为任意数组

  2. QT paintevent 事件, update()槽函数

    一界面重载函数 使用方法: 1在头文件里定义函数 protected: void paintEvent(QPaintEvent *event); 2 在CPP内直接重载 void ---------- ...

  3. mini6410基于linux2.6.36内核通过NFS启动根文件系统总结(四制作根文件系统及通过NFS挂载文件系统)

    http://blog.csdn.net/yinjiabin/article/details/7489563 根文件系统一般包括: 1)基本的文件系统结构,包含一些必须的目录,比如:/dev,/pro ...

  4. Xcode rename failed(修改类名失败)的解决办法

    1.前往文件夹~/Library/Developer/Xcode 2.删除Xcode文件夹下的DerivedData 3.等项目加载完成之后,即可rename

  5. review16

    java.lang包中的Math类包含许多用来进行科学计算的方法,这些方法可以直接通过类名调用. Math类中还有两个静态常量E和PI,分别表示自然对数和圆周率. 以下是Math类的常用方法 pulb ...

  6. ODPS中的TaskContext类里面的write函数

    ODPS中的TaskContext类有几个write函数 write(Record record)用来输出到默认输出表 write(Record record, String label)用来输出的l ...

  7. DecimalFormat数据格式函数

    DecimalFormat数据格式函数 class FormatDemo2{ public void format(String pattern, double value) { DecimalFor ...

  8. java:IO:file 类

    刷某一目录下的所有文件夹/文件 public class FileDemo2 { public static void main(String args[]) { File file = new Fi ...

  9. React native 开发工具 VSCode

    1.VSCODE下载地址:先下载VSCode软件 2.代码提示功能: 打开 VSCode ,然后 按住键盘 command+p,然后在vscode上面输入框 输入: "ext install ...

  10. Git_学习_01_ git 安装与配置

    参考:windows下Git BASH安装 二.参考资料 1. windows下Git BASH安装