我自己对asp.net 后台如何写事务一直感到疑惑,原因是何时使用回滚以及是否可以回滚成功(可能会失败哦)一直比较烦恼,
今天特地在SQL SERVER查询分析器中对事务报错后的情况作了仔细测试分析,得出如下总结,希望高手看过后发现错误,给予指正,搞清了这个原理,再后台写事务就能正确把握使用回滚了,谢谢了,以下为总结全文:
在sql server查询分析器中
一个事务中碰到错误的SQL 语句时:按错误语句类型分为如下四种情况1、如果报错的语句是insert语句这个时候如果xact_abort 为off(默认)的话,那么仅自动回滚该出错的语句,对事务其余部分不会
产生任何影响,就是等于把错误的SQL语句删除后再运行的话,跟删除前运行的效果是一样的。
如果是ON的话,那么立即终止整个事务,并且回滚整个事务2、如果碰到报错的语句是update语句那么这个时候无论xact_abort是什么值,都按xact_abort=ON时的效果处理,就是立即终止
事务并回滚整个事务3、如果碰到报错的语句是select语句那么无论xact_abort是什么值,事务中其余语句都不会执行(感觉好象都是先执行select语句
再考虑执行其它语句的),并且事务自动终止,由于其余语句都没试行,所以没必要考虑回滚4、如果碰到报错语句是delete语句这个时候如果xact_abort 为ON的话,那么立即终止整个事务,并且回滚整个事务,
如果xact_abort 为OFF(默认)的话,那么在语句报错后,事务就停止在那里,注:查看当前事务状态可以用xact_state()函数
今天特地在SQL SERVER查询分析器中对事务报错后的情况作了仔细测试分析,得出如下总结,希望高手看过后发现错误,给予指正,搞清了这个原理,再后台写事务就能正确把握使用回滚了,谢谢了,以下为总结全文:
在sql server查询分析器中
一个事务中碰到错误的SQL 语句时:按错误语句类型分为如下四种情况1、如果报错的语句是insert语句这个时候如果xact_abort 为off(默认)的话,那么仅自动回滚该出错的语句,对事务其余部分不会
产生任何影响,就是等于把错误的SQL语句删除后再运行的话,跟删除前运行的效果是一样的。
如果是ON的话,那么立即终止整个事务,并且回滚整个事务2、如果碰到报错的语句是update语句那么这个时候无论xact_abort是什么值,都按xact_abort=ON时的效果处理,就是立即终止
事务并回滚整个事务3、如果碰到报错的语句是select语句那么无论xact_abort是什么值,事务中其余语句都不会执行(感觉好象都是先执行select语句
再考虑执行其它语句的),并且事务自动终止,由于其余语句都没试行,所以没必要考虑回滚4、如果碰到报错语句是delete语句这个时候如果xact_abort 为ON的话,那么立即终止整个事务,并且回滚整个事务,
如果xact_abort 为OFF(默认)的话,那么在语句报错后,事务就停止在那里,注:查看当前事务状态可以用xact_state()函数
指定当 Transact-SQL 语句产生运行时错误时,Microsoft® SQL Server™ 是否自动回滚当前事务。语法
SET XACT_ABORT { ON | OFF }注释
当 SET XACT_ABORT 为 ON 时,如果 Transact-SQL 语句产生运行时错误,整个事务将终止并回滚。为 OFF 时,只回滚产生错误的 Transact-SQL 语句,而事务将继续进行处理。编译错误(如语法错误)不受 SET XACT_ABORT 的影响。对于大多数 OLE DB 提供程序(包括 SQL Server),隐性或显式事务中的数据修改语句必须将 XACT_ABORT 设置为 ON。唯一不需要该选项的情况是提供程序支持嵌套事务时。有关更多信息,请参见分布式查询和分布式事务。
参看我以前发的帖子,跟判断rollback前是否在事务中有关的.....
http://topic.csdn.net/u/20110226/09/b715c01d-df6d-45f1-840f-a872cf303016.html
http://topic.csdn.net/u/20110504/15/24efd2c0-e659-4421-b2bb-ee144e82a017.html
set xact_abort off
begin tran
select 1/0
print 'will be prited!'
commit tran
的情况
我总结的时候是选择了一个不存在的表进行了select查询,结果就如我总结中所述,你给出了一个除数为零的错误情况,这个时候的结果与xact_abort=off且报错语句为insert的时候情况相同,
暂时我也不知道该如何区分这两种select语句报错的情况,欢迎大家给予补充指正,谢谢....
if object_id('ta') is not null
drop table ta
go
create table ta(col1 int, col2 char)
goset xact_abort off
begin traninsert into ta
values(1/0, 'c')print 'will been printed'insert into ta
values(convert(int, 'ac'), 'd')print 'will not been printed'commit tran
但是第二个"will not been printed" 确实没有在我的总结结论中,其结果是没有执行任何语句且报错后事务自动终止了这么看来,我的总结已经是可以宣布作废了,谢谢各位关注和指正,接下来我换个总结的结论如下:在SQL SERVER的一个事务中语句报错后,产生以下几种状态xact_abort=off情况下
1\语句报错后,该语句自动回滚,且不影响事务的其它语句的运行
2\事务终止且自动回滚整个事务(这种情况没有被列在xact_abort=off的官方定义中)xact_abort=on的情况下
1\事务终止且自动回滚整个事务大家看看这样应该是对的吧,(这样对应用程序后台写事务时,判断是否可以rollback有了指导性意义了)
ID DESCR
----------- ----------
1 A
2 B set xact_abort off -- 关闭 xact_abort 的事务(默认关闭)
begin tran
insert into tb01 select 3,'C'
update tb01 set ID=1 where ID=2 -- 故意制造主键重复错误
insert into tb01 select 4,'D'
commit transelect * from tb01
ID DESCR
----------- ----------
1 A
2 B
3 C
4 D -->结果没有如楼主说讲的
"无论xact_abort是什么值,都按xact_abort=ON时的效果处理,就是立即终止事务并回滚整个事务"
个人认为,不必按DML语句来总结事务异常的处理.
SQL Server 2008提供了新语法 Begin try ... End Try ...
也能实现事务过程异常的自动回滚,楼主可以了解一下.
我主要是考虑在应用程序后台运用事务的时候,事务出错后该catch块怎么处理,
原来的考虑是如果存在事务就回滚,如果不存在事务就结束(就当做服务器数据库已经自动回滚了),
这样的的后台处理有问题吗?还有,如果不存在事务了,能否保证服务器的自动回滚是回滚了整个事务呢?(即使在默认xact_abort=off的默认情况下),我要的效果就是一旦事务出错,需要保证回滚整个事务
一旦事务出错,则自动回滚整个事务.(为何不呢)
---------------------------
SET XACT_ABORT { ON | OFF }
指定当 Transact-SQL 语句出现运行时错误时,SQL Server 是否自动回滚到当前事务
当 SET XACT_ABORT 为 ON 时,如果执行 Transact-SQL 语句产生运行时错误,则整个事务将终止并回滚。
当 SET XACT_ABORT 为 OFF 时,有时只回滚产生错误的 Transact-SQL 语句,而事务将继续进行处理。如果错误很严重,那么即使 SET XACT_ABORT 为 OFF,也可能回滚整个事务。编译错误(如语法错误)不受 SET XACT_ABORT 的影响。
对于大多数 OLE DB 提供程序(包括 SQL Server),必须将隐式或显示事务中的数据修改语句中的 XACT_ABORT 设置为 ON。唯一不需要该选项的情况是在提供程序支持嵌套事务时。
SET XACT_ABORT 的设置是在执行或运行时设置,而不是在分析时设置。