仔细研究了下,发现sql server里面的explicit transaction(显示事务)还是有点复杂的。以下是有些总结:

Commit transaction 会提交所有嵌套的transaction修改。但是如果嵌套的transaction里面有rollback tran to save point, 那么save point之后的部分会revert掉。

delete from dbo.numbertable

begin tran out1

     insert into dbo.numbertable values(1)

     insert into dbo.numbertable values(2)

     begin tran inn1

          insert into dbo.numbertable values(3)

          insert into dbo.numbertable values(4)

     save tran inn1SavePoint

          insert into dbo.numbertable values(5)

     rollback tran inn1SavePoint

     commit tran inn1

commit tran out1

@@TRANCOUNT可以用来记录当前session transaction的个数,对于嵌套的transaction来讲,每次begin transaction都让它加一,每次commit tran都会让它减一。所以在语句里面可以通过select @@TRANCOUNT 来检查当前是否在一个transaction里面。如果当前@@TRANCOUNT为0,那调用commit还是rollback都会出现语句错误。在嵌套的transaction里面,rollback是很特殊的,它会直接把@@TRANCOUNT设置为0。

begin tran

begin tran

begin tran

print @@trancount

rollback tran

print @@trancount

对于嵌套的transaction来讲,rollback的写法是很特殊。如果嵌套,rollback transaction后面是不能带transaction的name的,要带也只能是最外面的transaction的name。Rollback会抛弃所有嵌套transaction在rollback语句之前的修改。不过Rollback之后的更新依然会提交就是了,原因在于:rollback之后,@@trancount为0,那么rollback之后的语句就不属于explicit transaction, 属于autocmmit transaction了,自动提交。

delete from dbo.numbertable

begin tran t1

     insert into dbo.numbertable values(1)

     begin tran t2

          insert into dbo.numbertable values(2)

     rollback tran

     print 'after rollback in innert transaction, the transaction count is: '+cast(@@trancount, varchar(5))

     insert into dbo.numbertable values(3)

--commit tran

select * from dbo.numbertable

存储过程里面也可以begin transaction,如果调用存储过程的地方也begin transaction,那么这种情况也属于嵌套transaction,如果在存储过程里面rollback,得到的结果和上面一样。但是有一点特殊的地方在与,执行存储过程结束的时候会比较开始执行存储过程的@@trancount和结束时候@@trancount的值,如果不一样,Sqlserver会给出一个消息像“Transaction count after EXECUTE indicates that a COMMIT or ROLLBACK TRANSACTION statement is missing. Previous count = 1, current count = 0.”这个给出的消息并不会影响其后的执行。

CREATE PROCEDURE [dbo].[AddNumber]       

AS

BEGIN

     begin tran 

          insert into dbo.numbertable values(1)

          insert into dbo.numbertable values(2)

          insert into dbo.numbertable values(3)

     rollback tran

END

delete from dbo.numbertable

begin tran out1

exec dbo.addnumber

print @@trancount

insert into dbo.numbertable values(3)

select * from dbo.numbertable

如果在存储过程里面做rollback了,那到外面再做commit或者rollback都是没有效果的并且会报错,因为嵌套transaction内部的transaction一旦调用了rollback,@@trancount就为0了,在外面commit或rollback就会直接报错。比如如下sp,我想像在最外面rollback,那就出错了,因为sp里面语句rollback了。最后表里面始终会插入值3。

delete from dbo.numbertable

begin tran out1

exec dbo.addnumber

print @@trancount

insert into dbo.numbertable values(3)

rollback tran out1

select * from dbo.numbertable

所以对于嵌套的transaction来讲,如果内部transaction一旦rollback,就会给外部的transaction留下一个大坑。为了解决这个为题,有两种解决方案:

1.在外部的transaction里面检查@@trancount,如果这个值跟你代码begin tran的时候一致,那说明内部transaction没有rollback,那可以继续commit或者rollback。

delete from dbo.numbertable

begin tran t1

     insert into dbo.numbertable values(1)

     begin transaction t2

          insert into dbo.numbertable values(2)

     rollback tran

     if @@trancount = 1 

     begin

          insert into dbo.numbertable values(3)

          commit tran

     end

2.在所有的内部transaction里面,只能commit,不能rollback。如果必须rollback,那怎么办?save point就可以派上用场了。比如sp改成这样子:

ALTER PROCEDURE [dbo].[AddNumber]        

AS

BEGIN

     begin tran 

     save tran pp

          insert into dbo.numbertable values(1)

          insert into dbo.numbertable values(2)

          insert into dbo.numbertable values(3)

     rollback tran pp

     commit tran

END

begin tran out1

exec dbo.addnumber

print @@trancount

insert into dbo.numbertable values(3)

commit tran out1

原文链接

Sqlserver的Transaction做Rollback的时候要小心(转载)的更多相关文章

  1. sqlserver Distributed Transaction 分布式事务

    在webapi+ef+sqlserver开发项目时,利用transcope实现应用层级的事务时,偶尔会报分布式事务错误,而且很而复现,特别蛋疼.现将自己的解决方法初步整理下. 分析原因:搭建repos ...

  2. SqlServer+Topshelf+Quartznet做集群,定时任务分布式处理

    接触Quartznet之前,老东家用的是总监自己写的分布式任务框架,好用但是配置麻烦,unity,一个微软容器,配置节点错一个,整个使用到unity文件的项目全部跑不起来,这后果真的受不了... 目前 ...

  3. sqlserver 字段内容做in条件 列变成行显示

    sqlserver中 字段内容做in条件用到方法:CHARINDEX(value,situation) 列变行显示用到:stuff 详情自行查找. 例子: stuff((select ','+name ...

  4. SqlServer 一个查询语句以致tempdb增大55G (转载)

    SqlServer 一个查询语句导致tempdb增大55G 今天操作着服务器,突然右下角提示“C盘空间不足”! 吓一跳!~ 看看C盘,还有7M!!!这么大的C盘空间怎么会没了呢?搞不好等下服务器会动不 ...

  5. SqlServer突破亿级数据操作瓶颈(出处:转载)

    首先声明,我只是个程序员,不是专业的DBA,以下这篇文章是从一个问题的解决过程去写的,而不是一开始就给大家一个正确的结果,如果文中有不对的地方,请各位数据库大牛给予指正,以便我能够更好的处理此次业务. ...

  6. SqlServer 一个查询语句导致tempdb增大55G(转载)

    SqlServer 一个查询语句导致tempdb增大55G 今天操作着服务器,突然右下角提示“C盘空间不足”! 吓一跳!~ 看看C盘,还有7M!!!这么大的C盘空间怎么会没了呢?搞不好等下服务器会动不 ...

  7. Sqlserver 数据库恢复常见错误及解决(网站转载 留着备用)

    数据库恢复常见错误及解决 2009-04-13 11:25 1145人阅读 评论(0) 收藏 举报 数据库databasesqlserverusermicrosoftsql server 在sqlSe ...

  8. sqlserver锁表、解锁、查看销表 (转载)

    sqlserver中怎么锁表.解锁.查看销表呢,下面我以三个不同的实例给各位朋友详细介绍一下有需要的朋友可参考一下. 更多详细内容请查看:http://www.111cn.net/database/O ...

  9. Sqlserver内存管理:限制最大占用内存(转载)

    一.Sqlserver对系统内存的管理原则是:按需分配,且贪婪(用完不还).它不会自动释放内存,因此执行结果集大的sql语句时,数据取出后,会一直占用内存,直到占满机器内存(并不会撑满,还是有个最大限 ...

随机推荐

  1. vue代码上传服务器后背景图片404解决方法

    问题:代码上传服务器后,图片404,使用的font-awesome图标也是404 解决办法: 如果你用了vue-cil,那么在build目录下找到utils.js中的ExtractTextPlugin ...

  2. Mybatis通过GNDL语法引用静态常量或者枚举类型

    原因:mybatis 中mapper.xml 文件中需要静态常量的时候 使用: 先定义: public static String aa="aa"; ${@全路径类名称@静态变量| ...

  3. git命令小记

    1.git之tag git标签分为轻量级(lightweight)标签和含标注(annotated)标签.轻量级标签一般用于不会改变的分支,含标注的标签包含详细的信息. 轻量级标签: git tag ...

  4. maven官方教程

    What is Maven? At first glance Maven can appear to be many things, but in a nutshell Maven is an att ...

  5. CTSC 2018 游记

    day0 李总提前一天放假,回家颓整理行李... 然而我... 早上:睡觉... 中午:睡觉... 晚上:睡觉去火车站... 吃了几把鸡,本来想带李总入坑,但他挥手拒绝然后被李总带进了炸金花的坑... ...

  6. [NOI 2016]循环之美

    Description 题库链接 给出十进制下的 \(n,m,k\) ,求 \(\frac{i}{j},i\in[1,n],j\in[1,m]\) 在 \(k\) 进制下不同的纯循环小数个数. 纯循环 ...

  7. JS实现金额转换(将输入的阿拉伯数字)转换成中文

    <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/ ...

  8. ABP的依赖注入

    目录 说说ABP的依赖注入 代码追踪 说说ABP的依赖注入 上篇abp运行机制分析分析了ABP在启动时,都做了那些事:这篇我们来说说ABP的最核心的一部分:依赖注入(DependencyInjecti ...

  9. openstack-on-centos7之环境准备

    centos7配置静态ip ifconfig查看网卡信息并获取到网卡的名称eth0s3 ifconfig 进入到网卡配置目录 cd /etc/sysconfig/network-scripts/ 找到 ...

  10. cakephp怎么默认显示index/index文件

    在配置好cakephp之后,我们输入网址后都一般默认显示index/index 文件,那么怎么设置呢? 1.D:\www\cakephp\app\Config\routes.php