为什么事务没有回滚!

--事务的原子性要求事务要么全部完成,要么全部不完成,不可能停滞在某个中间状态。
--然而,我的事务却没有“回滚”,为此还导致了异常数据的发生,为什么?

这是一个发生在我工作中的真实的案例,在用户问我的时候我当时也SB了,
在我理解了这背后的原理后,我虽然接受了SQL Server在某些场景下不回滚的设计使然,但不得不吐槽,这个功能真不爽!
下面我利用一个样例来描述这个问题:

--创建test1表
CREATE TABLE [dbo].[test1](
    [id] [int] NOT NULL,
    [testname] [varchar](10) NULL
) ON [PRIMARY]
GO

现在执行一个事务,事务中包含两个insert操作,其中第一个insert操作的testname字段超过了最大长度10

--显示执行一个事务,插入两行数据,其中第一行的testname字段超过了最大长度

         BEGIN TRANSACTION;
         --SELECT 1
         --FROM test;
         INSERT INTO [dbo].[test1]
                                  ([id], [testname]
                                  )
         VALUES
                (1, '123456789101'
                );
         INSERT INTO [dbo].[test1]
                                  ([id], [testname]
                                  )
         VALUES
                (888, '12345'
                );
         COMMIT TRANSACTION;

如预料的一样,SQL Server在执行第一条语句时报错

“按理”说来,这个事务执行会失败,第二条插入语句会回滚,但实际结果却是:

select * from [dbo].[test1]

在某些场景下,这会导致异常数据的发生。

 

为什么会这样呢??

据MSDN,默认情况,SQL Server并不会回滚事务,即使事务中的某个语句报错,事务还是会继续执行下去,除非非常严重的错误(serverity level is greater or equals 16)。
这是由数据库选项XACT_ABORT决定的,默认XACT_ABORT为OFF,

When SET XACT_ABORT is OFF, in some cases only the Transact-SQL statement that raised the error is rolled back and the transaction continues processing. Depending upon the severity of the error, the entire transaction may be rolled back even when SET XACT_ABORT is OFF. OFF is the default setting.

如果想规避这个问题,微软告诉我们需要把XACT_ABORT设置为On,这样一个事务中任务一个语句报错都会导致整个事务回滚。

SET XACT_ABORT ON

当然,你也可以使用try、catch人工捕获错误以便进行回滚或者在程序中使用事务。

 

我在想为什么会有这么DT的设计呢?

我们学事务的第一堂课里面就讲了事务的原子性要求:事务要么全部执行,要么全部失败,不会存在中间状态。
但SQL Server为什么默认不回滚呢?百思不得其解。
求助MSDN时邹大侠给的一个解释虽然有道理(谢谢邹大侠),但还是觉得不够完美,因为即使是为了能够让开发人员自己来控制事务的状态,也不应该把XACT_ABORT默认设置为OFF,相反,如果设置为On倒是可以接受。

 

 

期待其他大神们给予指导。

时间: 2024-09-19 20:31:16

为什么事务没有回滚!的相关文章

java 事务 不回滚,这边进行处理的时候发现添加失败的时候,发现for里面的数据会插入到数据库中

问题描述 java 事务 不回滚,这边进行处理的时候发现添加失败的时候,发现for里面的数据会插入到数据库中 2C 解决方案 你确定已经开启事务了? 解决方案二: 你的这段代码就是执行了批量插入操作,没有涉及到添加事务的处理啊. 解决方案三: 不知道你是用了什么事务处理机制,光看这段代码跟事务没有一点关系! 解决方案四: 显然没有添加事务处理机制. 解决方案五: Transaction 呢? 解决方案六: 没看到事务语句...... 解决方案七: 想让rollback,你至少得用事务吧,都没用事

spring事务注解@Transactional事务不回滚

问题描述 spring事务注解@Transactional事务不回滚 如题: public interface A { public void A(); } public class B implements A{ public void A(){ B();} @Transactional public void B(){ //删除数据 //两者之前发生异常了... //添加数据 } } 如果将@Transactional注解放在某一service实现类的某一非入口方法,发现数据不会回滚,请问大

spring 事务 回滚-spring @Transactional 事务不能回滚

问题描述 spring @Transactional 事务不能回滚 在spring的配置文件里配置如下: <!-- enable the configuration of transactional behavior based on annotations --> <tx:annotation-driven transaction-manager="txManager"/> <!-- a PlatformTransactionManager is sti

求大神帮忙 spring aop 方式事务不回滚怎么搞?

问题描述 求大神帮忙 spring aop 方式事务不回滚怎么搞? spring 版本 4.1.7 代码如下: 表: CREATE TABLE users (id int(11) unsigned NOT NULL AUTO_INCREMENT,nick_name varchar(100) DEFAULT NULL,password varchar(100) DEFAULT NULL, PRIMARY KEY (id) ) ENGINE=InnoDB AUTO_INCREMENT=5 DEFAU

maven项目spring3+mybatis3事务不回滚

问题描述 maven项目spring3+mybatis3事务不回滚 注:该项目的mapper和service均未注入到spring ,service中的mapper获取是用的spring上下文获取的,只有controller注入到spring中了. 问题:这种方式开发要怎样注入事务?使用spring事务拦截失效,不知道是不是我没配对,求D神指教 解决方案 解决方案二: http://blog.csdn.net/evankaka/article/details/45478007,看看这里,

为何事务不能回滚?

问题描述 weblogic下的ejb出现异常,代码跟踪已经执行回滚代码了,为何中间操作数据库的数据行为不能回滚到事务开始前?说明:1.中间很多方法都是用statment做参数,同一个statment的传参2.应用和数据库服务的网咯连接比较慢.求解 问题补充:lt0604 写道 解决方案 你应该要清楚的是事务是建立在连接上的.而不是statment.先在你的执行方法里面使用statment.getConnection().getAutoCommit()是不是为false.又或者传参的时候的stat

MySql事务无法回滚的原因有哪些_Mysql

使用MySQL时,如果发现事务无法回滚,但Hibernate.Spring.JDBC等配置又没有明显问题时,不要苦恼,先看看MySQL创建的表有没有问题,即表的类型. InnoDB和MyISAM是在使用MySQL最常用的两个表类型,各有优缺点,视具体应用而定.基本的差别为:MyISAM类型不支持事务处理等高级处理,而InnoDB类型支持.MyISAM类型的表强调的是性能,其执行数度比InnoDB类型更快,但是不提供事务支持,而InnoDB提供事务支持已经外部键等高级数据库功能. MyIASM是I

Mysql非事务表回滚失败的现象

执行ROLLBACK(回滚)时,如果收到下述消息,表示事务中使用的1个或多个表不支持事务: 警告:某些更改的非事务性表不能被回滚. 这些非事务性表不受ROLLBACK语句的影响. 如果在事务中意外地混合了事务性表和非事务性表,导致该消息的最可能原因是,你认为本应是事务性的表实际上不是.如你试图使用MySQLd服务器不支持的事务性存储引擎(或用启动选项禁止了它)创建表,就可能出现该情况.如果mysqld不支持存储引擎,它将以MyISAM表创建表,这是非事务性表. 可使用下述语句之一检查表的标类型:

springmvc+hibernate整合事务不回滚,求解

问题描述 最近心血来潮研究下了springmvc,发现比struts2好用多了,配置也方便,捣鼓了一阵,最后想把hibernate也整进去,结果悲剧就来了,事务就是不回滚,实在没招了,哪位大侠给看下,上代码 springmvc-servlet.xml <mvc:annotation-driven/><!-- 扫描注解时,将service,DAO层的注解排除,只扫描Controller注解 --><context:component-scan base-package=&quo

spring + hibernate +jta 事务不能回滚问题

问题描述 spring 配置文件<bean id="idcJDBC" class="com.atomikos.jdbc.SimpleDataSourceBean"><property name="uniqueResourceName"><value>db_idcbase</value></property><property name="xaDataSourceClass