转自  :SqlServer中嵌套事务使用--事务计数指示 BEGIN 和 COMMIT 语句的数目不匹配 --根本问题

问题:

1. System.Data.SqlClient.SqlException (0x80131904): EXECUTE 后的事务计数指示 BEGIN 和 COMMIT 语句的数目不匹配。上一计数 = 1,当前计数 = 0。

2. EXECUTE 后的事务计数指示 BEGIN 和 COMMIT 语句的数目不匹配。上一计数 = 0,当前计数 = 1。

后面的内容,是我之前写的东西,主要是一些测试代码,但是呢,我没有很深入的理解。现在直接说清楚本质的东西,把后面的精华再提上来说。 

  • 提交的事务不能撤销或回滚。
  • 当不存在打开的事务时,@@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

注意:save tran 命令,不会使@@trancount加1

分析:

只要提交或者回滚事务后,程序内部改变了事务参数@@TRANCOUNT,就会出上述的错误,无一例外。

试图直接用Sql "  set @@trancount = 1;",这是sqlserver 不允许做的。

各位,出现上面的错误,最多的可能是在嵌套事务中。

如果不嵌套:没有begin tran前,@@trancount为0;  begin tran后,@@trancount  此时为1;完事后就commit或rollback,@@trancount  此时为0;--不般我们是写不错的。

嵌套呢

    看看我之前写的一个存储过程:

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

.......

....做事去了

.......

  1. if @error_code != 0 or @logErrorCode != 1
  2. begin
  3. rollback tran current_tran
  4. set @error_code = -1; -- 失败
  5. end
  6. else
  7. begin
  8. commit tran current_tran
  9. set @error_code = 1; -- 成功
  10. end
  1. if @error_code != 0 or @logErrorCode != 1
  2. begin
  3. rollback tran current_tran
  4. set @error_code = -1; -- 失败
  5. end
  6. else
  7. begin
  8. commit tran current_tran
  9. set @error_code = 1; -- 成功
  10. end

有没有问题?(current_tran是保存点哈,不明白的,后面有比较详细的介绍)

我用了好久了(在一个项目里面),可是突然有一天,也就是今天,它出事了。原因嘛,虽然写的是嵌套的,之前都没有嵌套调到过。

我在外围开了一个事务,再来调这个存储过程,当它 commit tran current_tran 时(rollback tran current_tran是不会有事的),会出什么错误?如果你不能很明确的告诉我,说明你还没有理解得深刻。做个选择吧?

1."...BEGIN 和 COMMIT 语句的数目不匹配。上一计数 = 0,当前计数 = 1。"

2."...BEGIN 和 COMMIT 语句的数目不匹配。上一计数 = 1,当前计数 = 0。

答案:【2】。

线索分析:我是在外部开了一个事务的,所以在未进入该存储过程以前@@trancount的值应该为1;进入时,save tran current_tran, @@trancount值没有变;完事的,执行commit tran current_tran,@@trancount的值应该为0;--所以,进入前,出来后,@@trancount值发生了改变,SqlServer不干了(原因,自己去想吧:拆散了begin tran 配对)。

怎么解决

1.进入子事务前先记录@@trancount,我们用变量@trancount来记录。

2. 提交子事务前,先判断之前的@trancount是否为0;为0表示"该事务"前没有事务调用,可以直接提交事务;不为0,表明进入该事务前已经有一个事务,该事务是子事务,不能提交。

  1. -- 如果当前计数为0,则提交.
  2. -- 因为Commit tran ,@@TRANCOUNT会减1。嵌套事务时,调用该存在过程(作为子过程,此时@@TRANCOUNT > 0),
  3. -- 只是保存了tran, @@TRANCOUNT没有发生改变;直接Commit会使@@TRANCOUNT减1,会打破事务对(Begin Tran)
  4. if(@trancount = 0)
  5. begin
  6. commit tran current_tran
  7. end
  8. set @error_code = 1; -- 成功
  1. -- 如果当前计数为0,则提交.
  2. -- 因为Commit tran ,@@TRANCOUNT会减1。嵌套事务时,调用该存在过程(作为子过程,此时@@TRANCOUNT > 0),
  3. -- 只是保存了tran, @@TRANCOUNT没有发生改变;直接Commit会使@@TRANCOUNT减1,会打破事务对(Begin Tran)
  4. if(@trancount = 0)
  5. begin
  6. commit tran current_tran
  7. end
  8. set @error_code = 1; -- 成功

SqlServer中嵌套事务使用--事务计数指示 BEGIN 和 COMMIT 语句的数目不匹配 --根本问题的更多相关文章

  1. EF非常见错误:EXECUTE 后的事务计数指示 BEGIN 和 COMMIT 语句的数目不匹配

    EF非常见错误:EXECUTE 后的事务计数指示 BEGIN 和 COMMIT 语句的数目不匹配 问题原因: 两个表A\B之间存在外键关系,当插入表A的时候,A的外键B在B表中不存在可以引起这个问题: ...

  2. EXECUTE 后的事务计数指示 BEGIN 和 COMMIT 语句的数目不匹配

    代码中的事务包含了存储过程中的事务.

  3. System.Data.SqlClient.SqlException (0x80131904): EXECUTE 后的事务计数指示 BEGIN 和 COMMIT 语句的数目不匹配。上一计数 = 1,当前计数 = 0。 EXECUTE 后的事务计数指示 BEGIN 和 COMMIT 语句的数目不匹配。上一计数 = 1,当前计数 = 0。

    EF使用ExecuteSqlCommand(db.Database.ExecuteSqlCommand("exec proc_DeleteCaseInfo_Output @caseID&qu ...

  4. EXECUTE 后的事务计数指示缺少了 COMMIT 或 ROLLBACK TRANSACTION 语句。上一计数 = 1,当前计数 = 2

    理解这一句话: 一个begin tran会增加一个事务计数器,要有相同数量的commit与之对应,而rollback可以回滚全部计数器 这个错误一般是出现在嵌套事务中. 测试环境 sql 2008 例 ...

  5. sqlserver中创建包含事务的存储过程

    什么是事务     事务时包含1条或多条语句的逻辑单元.事务中的语句是一个整体,要么一起提交,要么一起撤销.事务在提交前可以回滚,一旦提交就不能撤销修改了,是永久性的修改.   为什么使用事务     ...

  6. sql server中嵌套事务*

    转自 https://www.cnblogs.com/guanjie20/archive/2013/02/17/2914488.html 我们在写事务时经常遇到的问题如下: 消息 266,级别 16, ...

  7. 浅谈.net中数据库操作事务

    .net中的事务 关键几点 概念:1:什么是事务 2:什么时候用事务 3:基本的语法 (1): 事务(Transaction)是访问并可能更新数据库中各种数据项的一个程序执行单元(unit).事务通常 ...

  8. SQLServer中的事务与锁

    事务:保持逻辑数据一致性与可恢复性,必不可少的利器. 锁:多用户访问同一数据库资源时,对访问的先后次序权限管理的一种机制,没有他事务或许将会一塌糊涂,不能保证数据的安全正确读写. 死锁:是数据库性能的 ...

  9. 【SqlServer】解析SqlServer中的事务

    目录结构: contents structure [+] 事务是什么 控制事务 数据并发访问产生的影响 事务的隔离级别 锁 NOLOCK.HOLDLOCK.UPDLOCK 死锁分析 在这篇Blog中, ...

随机推荐

  1. eclipse中如何去除警告:Class is a raw type. References to generic type Class<T> should be parameterized

    转自:https://blog.csdn.net/zwr_1022/article/details/78583872 解决前的源代码: public class test {public static ...

  2. 搭建Node+NPM+Grunt+Ruby开发环境

    序 最近尝试了一下CoffeeScript,和Sass,不得不说这两个搭配起来的确是不错的选择,熟悉以后基本上开发就比较快速了. 当然要开发这个首先需要搭建环境,这里就需要有Node.NPM.Grun ...

  3. npm下载模块提速方法

    通过config配置指向国内镜像源,命令如下 npm config set registry https://registry.npm.taobao.org 然后可以查看是否配置成功 npm conf ...

  4. my emacs configuration

    modified from https://github.com/flyingmachine/emacs-for-clojure ;;;; ;; Packages ;;;; ;; Define pac ...

  5. AtCoder Beginner Contest 052

    没看到Beginner,然后就做啊做,发现A,B太简单了...然后想想做完算了..没想到C卡了一下,然后还是做出来了.D的话瞎想了一下,然后感觉也没问题.假装all kill.2333 AtCoder ...

  6. hdu1506 直方图中最大的矩形 单调栈入门

    hdu1506 直方图中最大的矩形 单调栈入门 直方图是由在公共基线对齐的矩形序列组成的多边形.矩形具有相同的宽度,但可能具有不同的高度.例如,左侧的数字显示了由高度为2,1,4,5,1,3,3的矩形 ...

  7. codevs3145 汉诺塔游戏

    3145 汉诺塔游戏  时间限制: 1 s  空间限制: 32000 KB  题目等级 : 白银 Silver     题目描述 Description 汉诺塔问题(又称为河内塔问题),是一个大家熟知 ...

  8. 配置vmware的固定ip

    一 .概述 为什么要配置固定IP呀?这个很容易解释啊,因为配置集群要设置固定IP(主结点需要管理子结点,通过固定IP识别机器),因为你访问虚拟机方便(不固定IP访问前还需要先查下虚拟机当前分配IP,比 ...

  9. Jmeter 跨线程组传递参数 之两种方法

    终于搞定了Jmeter跨线程组之间传递参数,这样就不用每次发送请求B之前,都需要同时发送一下登录接口(因为同一个线程组下的请求是同时发送的),只需要发送一次登录请求,请求B直接用登录请求的参数即可,直 ...

  10. 3.过滤数据 ---SQL

    一.使用WHERE子句 SELECT prod_name, prod_price FROM Products WHERE prod_price = 3.49; 输出▼ prod_name prod_p ...