为什么事务没有回滚!

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

这是一个发生在我工作中的真实的案例,在用户问我的时候我当时也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-11-07 04:42:35

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

代码配置都没问题,为什么事务不回滚(了解Mysql数据库引擎)

前几天开发中遇到了一个问题,在进行调试的过程中发现配置在service层的事务不起作用,抛出异常后数据库的更新还是成功了,事务并没有回滚,然后就开始各种检查,查看spring的事务是否配置正确,进入更新方法时是否开启了事务,经过检查之后发现一切都正常,那为什么事务不回滚呢?问题出在了一个很难会去考虑的地方(数据库里创建的表不支持事务). Mysql数据库默认的创建表的引擎是:MYISAM,使用这种引擎的表效率高,但是不支持事务,所以我们在建表时最好是根据需求手动去指定我们需要的引擎,下面是一个能

Spring事务异常回滚,捕获异常不抛出就不会回滚(转载) 解决了我一年前的问题

最近遇到了事务不回滚的情况,我还考虑说JPA的事务有bug? 我想多了.......    为了打印清楚日志,很多方法我都加tyr catch,在catch中打印日志.但是这边情况来了,当这个方法异常时候 日志是打印了,但是加的事务却没有回滚. 例:     类似这样的方法不会回滚 (一个方法出错,另一个方法不会回滚) : if(userSave){ try { userDao.save(user); userCapabilityQuotaDao.save(capabilityQuota); }

Spring事务异常回滚,捕获异常不抛出就不会回滚

最近遇到了事务不回滚的情况,我还考虑说JPA的事务有bug? 我想多了.......    为了打印清楚日志,很多方法我都加tyr catch,在catch中打印日志.但是这边情况来了,当这个方法异常时候 日志是打印了,但是加的事务却没有回滚. 例:     类似这样的方法不会回滚 (一个方法出错,另一个方法不会回滚) : [html] view plain copy if(userSave){ try { userDao.save(user); userCapabilityQuotaDao.s

JDBC PreparedStatement ,CallableStatement,以及事务,回滚举例

程序中用到的类,文件,jar 代码: 1,文件:db.properties文件内容 user=rootpassword=123url=jdbc:mysql:///student_dbdriver=com.mysql.jdbc.Driveraaa 2,类Utils.class import java.io.InputStream;import java.sql.Connection;import java.sql.DriverManager;import java.sql.SQLException

spring + myBatis 常见错误:注解事务不回滚

最近项目在用springMVC+spring+myBatis框架,在配置事务的时候发现一个事务不能回滚的问题. 刚开始配置如下:springMVC.xml配置内容: spring.xml配置内容 从上面两个配置文件看出,开始的时候我把Service配置在springMVC中的.但是,事务注解我配置在了spring中.这样就会出现问题了.因为spring的容器(applicationContext)和springMVC的(applicationContext)是不同的. spring容器加载得时候

SpringMVC+Ibatis事务不回滚的问题

在使用SpringMvc的时候,大多数人都会遇到事务不回滚的问题.其实事务在Spring里面使用起来很简单,只要配置正确了,知识一个标签的事. 下面我就给大家说一下我是怎么解决这个问题的. 一.配置扫描标签时 <!-- springmvc的配置文件中不扫描带有@Service注解的类 --> <context:component-scan base-package="com.dds"> <context:exclude-filter type="

Spring AOP声明式事务异常回滚

转:http://hi.baidu.com/iduany/item/20f8f8ed24e1dec5bbf37df7 近日测试用例,发现这样一个现象:在业务代码中,有如下两种情况,比如:throw new RuntimeException("xxxxxxxxxxxx"); 事物回滚throw new Exception("xxxxxxxxxxxx"); 事物没有回滚 自以为很了解事物,或许时间久远的缘故,没分析出来何故,遂查阅了下资料,写下了如下的内容,供参考: 1

sqlserver事务与回滚

如果要在Production执行数据改动必须小心,可以使用事务提前验证一下自己写的SQL是不是你期望的.尤其是Update的where 条件有问题的话,跟新的记录就会超出预期的范围.如下面的语句,一着急我差点把cartid = 678417 忘了,要是在Production执行影响就大了. BEGIN TRANSACTION update cartitem set deleted=0 where cartid = 678417 and modifieddate > '2014-08-07' se

MySql事务无法回滚的原因

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

springmvc mybatis 声明式事务管理回滚失效,(checked回滚)捕捉异常,传输错误信息

一.知识点及问题 后端框架: Spring .Spring mvc .mybatis 业务需求: client先从服务端获取用户大量信息到client,编辑完毕之后统一Post至服务端,对于数据的改动要么全成功,要么全失败,所以须要使用事务支持. 问题: 配置Spring声明式事务,运行中出现异常未回滚.从网上查询得到一開始是自己的配置出了问题,因为配置文件的载入顺序决定了容器的载入顺序导致Spring事务没有起作用. 详情例如以下: 因为採用的是SpringMVC. MyBatis,故统一採用