加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 站长学院 > MsSql教程 > 正文

SqlServer中嵌套事务使用--事务计数指示 BEGIN 和 COMMIT 语句的

发布时间:2020-12-12 16:05:23 所属栏目:MsSql教程 来源:网络整理
导读:问题: 1. System.Data.SqlClient.SqlException (0x80131904): EXECUTE 后的事务计数指示 BEGIN 和 COMMIT 语句的数目不匹配。上一计数 = 1,当前计数 = 0。 2. EXECUTE 后的事务计数指示 BEGIN 和 COMMIT 语句的数目不匹配。上一计数 = 0,当前计数 = 1。

问题:

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;--不般我们是写不错的。

嵌套呢

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

??????????????

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

.......

....做事去了

.......

?

[sql] view plain copy print ?
  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,表明进入该事务前已经有一个事务,该事务是子事务,不能提交。

[sql] view plain copy print ?
  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 事务相关:《嵌套事务(一):.NET中嵌套事务运用的一点思考》

         《嵌套事务(二):SqlServer中嵌套事务使用》

???????????????    ?   《SqlServer 嵌套事务机制 测试 》

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读