SqlServer中嵌套事务使用--事务计数指示 BEGIN 和 COMMIT 语句的数目不匹配 --根本问题
转自 :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;--不般我们是写不错的。
嵌套呢:
看看我之前写的一个存储过程:
- declare @trancount int --commit,rollback只控制本存储过程
- set @trancount = @@trancount;
- if (@trancount=0) /*判断事务记数,根据情况确定使用保存点或者新建一个事务*/
- begin tran current_tran--当前事务点,rollback、commit都从这里开始
- else
- save tran current_tran
- declare @trancount int --commit,rollback只控制本存储过程
- set @trancount = @@trancount;
- if (@trancount=0) /*判断事务记数,根据情况确定使用保存点或者新建一个事务*/
- begin tran current_tran--当前事务点,rollback、commit都从这里开始
- else
- save tran current_tran
.......
....做事去了
.......
- if @error_code != 0 or @logErrorCode != 1
- begin
- rollback tran current_tran
- set @error_code = -1; -- 失败
- end
- else
- begin
- commit tran current_tran
- set @error_code = 1; -- 成功
- end
- if @error_code != 0 or @logErrorCode != 1
- begin
- rollback tran current_tran
- set @error_code = -1; -- 失败
- end
- else
- begin
- commit tran current_tran
- set @error_code = 1; -- 成功
- 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,表明进入该事务前已经有一个事务,该事务是子事务,不能提交。
- -- 如果当前计数为0,则提交.
- -- 因为Commit tran ,@@TRANCOUNT会减1。嵌套事务时,调用该存在过程(作为子过程,此时@@TRANCOUNT > 0),
- -- 只是保存了tran, @@TRANCOUNT没有发生改变;直接Commit会使@@TRANCOUNT减1,会打破事务对(Begin Tran)
- if(@trancount = 0)
- begin
- commit tran current_tran
- end
- set @error_code = 1; -- 成功
- -- 如果当前计数为0,则提交.
- -- 因为Commit tran ,@@TRANCOUNT会减1。嵌套事务时,调用该存在过程(作为子过程,此时@@TRANCOUNT > 0),
- -- 只是保存了tran, @@TRANCOUNT没有发生改变;直接Commit会使@@TRANCOUNT减1,会打破事务对(Begin Tran)
- if(@trancount = 0)
- begin
- commit tran current_tran
- end
- set @error_code = 1; -- 成功
SqlServer中嵌套事务使用--事务计数指示 BEGIN 和 COMMIT 语句的数目不匹配 --根本问题的更多相关文章
- EF非常见错误:EXECUTE 后的事务计数指示 BEGIN 和 COMMIT 语句的数目不匹配
EF非常见错误:EXECUTE 后的事务计数指示 BEGIN 和 COMMIT 语句的数目不匹配 问题原因: 两个表A\B之间存在外键关系,当插入表A的时候,A的外键B在B表中不存在可以引起这个问题: ...
- EXECUTE 后的事务计数指示 BEGIN 和 COMMIT 语句的数目不匹配
代码中的事务包含了存储过程中的事务.
- 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 ...
- EXECUTE 后的事务计数指示缺少了 COMMIT 或 ROLLBACK TRANSACTION 语句。上一计数 = 1,当前计数 = 2
理解这一句话: 一个begin tran会增加一个事务计数器,要有相同数量的commit与之对应,而rollback可以回滚全部计数器 这个错误一般是出现在嵌套事务中. 测试环境 sql 2008 例 ...
- sqlserver中创建包含事务的存储过程
什么是事务 事务时包含1条或多条语句的逻辑单元.事务中的语句是一个整体,要么一起提交,要么一起撤销.事务在提交前可以回滚,一旦提交就不能撤销修改了,是永久性的修改. 为什么使用事务 ...
- sql server中嵌套事务*
转自 https://www.cnblogs.com/guanjie20/archive/2013/02/17/2914488.html 我们在写事务时经常遇到的问题如下: 消息 266,级别 16, ...
- 浅谈.net中数据库操作事务
.net中的事务 关键几点 概念:1:什么是事务 2:什么时候用事务 3:基本的语法 (1): 事务(Transaction)是访问并可能更新数据库中各种数据项的一个程序执行单元(unit).事务通常 ...
- SQLServer中的事务与锁
事务:保持逻辑数据一致性与可恢复性,必不可少的利器. 锁:多用户访问同一数据库资源时,对访问的先后次序权限管理的一种机制,没有他事务或许将会一塌糊涂,不能保证数据的安全正确读写. 死锁:是数据库性能的 ...
- 【SqlServer】解析SqlServer中的事务
目录结构: contents structure [+] 事务是什么 控制事务 数据并发访问产生的影响 事务的隔离级别 锁 NOLOCK.HOLDLOCK.UPDLOCK 死锁分析 在这篇Blog中, ...
随机推荐
- SpringBoot @RequestBody 中文乱码
今天突然想学习一下Restful风,详细的我就不赘述了,我的理解是同一个请求路径根据请求方式不同进行不同的处理 如四种提交方式,这里推荐一个插件Postman,可以模仿各种请求类型,自行百度安装吧 G ...
- switch()出现警告warning:enumeration value ‘xxx’ not handled in switch
enumeration value ... not handled in switch 如果在switch中使用使用枚举类型,如:switch(枚举类型) 枚举类型的个数没有全部列出,就会报这个警告
- linux下删除3分钟之前指定文件夹下的指定类型文件
如果想要修改crontab,一般做以下的几步就可以了 将crontab 推到一个自定义的文件上 crontab -l>;tmp 编辑这个文件,做需要的修改 vi tmp 推回crontab cr ...
- 深入剖析ASP.NET Core2.1部署模型,你会大吃一惊
---------------------------- 以下内容针对 ASP.NET Core2.1版本,2.2推出windows IIS进程内寄宿 暂不展开讨论---------------- ...
- MYSQL数据库设计规范11111
MYSQL数据库设计规范 1.数据库命名规范 采用26个英文字母(区分大小写)和0-9的自然数(经常不需要)加上下划线'_'组成; 命名简洁明确(长度不能超 ...
- Solr 6.7学习笔记(06)-- spell check
拼写检查也是搜索引擎必备的功能.Solr中提供了SpellCheckComponent 来实现此功能.我看过<Solr In Action>,是基于Solr4.X版本的,那时Suggest ...
- poj3186(区间dp)
题目链接:http://poj.org/problem?id=3186 题意:给一行n个数,每次可以取出行首或者行末的数,如果第ai是第i次取出的,可以得到ai*i的收益,求最大的总收益: 思路:区间 ...
- 已知单链表的数据元素为整型数且递增有序,L为单链表的哨兵指针。编写算法将表中值大于X小于Y的所有结点的顺序逆置。(C语言)
对此题目的完整示例可直接运行代码如下: #include <stdio.h> #include <stdlib.h> typedef struct LNode{ int dat ...
- java.sql.SQLException: No suitable driver found for jdbc:hive://localhost:10000/default
error: java.sql.SQLException: No suitable driver found for jdbc:hive://localhost:10000/default at ja ...
- Net Core WebApi几种版本控制对比
Net Core WebApi几种版本控制对比 一.版本控制的好处: (1)有助于及时推出功能, 而不会破坏现有系统. (2)它还可以帮助为选定的客户提供额外的功能. API 版本控制可以采用不同的方 ...