我自己对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()函数

解决方案 »

  1.   

    SET XACT_ABORT
    指定当 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。唯一不需要该选项的情况是提供程序支持嵌套事务时。有关更多信息,请参见分布式查询和分布式事务。 
      

  2.   

    但是你如果搜索.net后台使用事务的写法,基本千篇一律的都是在一个catch块里加个rollback(),根本没判断是否存在有效事务可以回滚,这个现象让我无法接受啊,
    参看我以前发的帖子,跟判断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
      

  3.   


    set xact_abort off
    begin tran
      select 1/0 
      print 'will be prited!'
    commit tran
      

  4.   

    非常感谢找到一个错误,你的情况应该归属于报错语句是select且xact_abort=off
    的情况
    我总结的时候是选择了一个不存在的表进行了select查询,结果就如我总结中所述,你给出了一个除数为零的错误情况,这个时候的结果与xact_abort=off且报错语句为insert的时候情况相同,
    暂时我也不知道该如何区分这两种select语句报错的情况,欢迎大家给予补充指正,谢谢....
      

  5.   


    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
      

  6.   

    第一个"will been print" 其实还是符合我总结的结论的,
    但是第二个"will not been printed" 确实没有在我的总结结论中,其结果是没有执行任何语句且报错后事务自动终止了这么看来,我的总结已经是可以宣布作废了,谢谢各位关注和指正,接下来我换个总结的结论如下:在SQL SERVER的一个事务中语句报错后,产生以下几种状态xact_abort=off情况下
    1\语句报错后,该语句自动回滚,且不影响事务的其它语句的运行
    2\事务终止且自动回滚整个事务(这种情况没有被列在xact_abort=off的官方定义中)xact_abort=on的情况下
    1\事务终止且自动回滚整个事务大家看看这样应该是对的吧,(这样对应用程序后台写事务时,判断是否可以rollback有了指导性意义了)
      

  7.   

    这个官方的定义好象已经不正确了吧,以上已经列出了很多为off的时候就自动终止事务且回滚整个事务的列子了,而且又不属于编译错误,
      

  8.   

    不同意楼主总结的第2点喔, 理论就不多说了, 举个反例就行.create table tb01 (ID int primary key,DESCR char(10))insert into tb01 select 1,'A' union all select 2,'B'select * from tb01
    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时的效果处理,就是立即终止事务并回滚整个事务"
      

  9.   

    还有, 严格来讲, 第3点,第4点未必完全正确. 就不举例了.
    个人认为,不必按DML语句来总结事务异常的处理.
    SQL Server 2008提供了新语法 Begin try ... End Try ...
    也能实现事务过程异常的自动回滚,楼主可以了解一下.
      

  10.   

    那这样的话,最终事务状态应该有几种呢?
    我主要是考虑在应用程序后台运用事务的时候,事务出错后该catch块怎么处理,
    原来的考虑是如果存在事务就回滚,如果不存在事务就结束(就当做服务器数据库已经自动回滚了),
    这样的的后台处理有问题吗?还有,如果不存在事务了,能否保证服务器的自动回滚是回滚了整个事务呢?(即使在默认xact_abort=off的默认情况下),我要的效果就是一旦事务出错,需要保证回滚整个事务
      

  11.   

    简单来讲,设置set xact_abort=on, 
    一旦事务出错,则自动回滚整个事务.(为何不呢)
      

  12.   

    这个在asp.net后台程序里可以设置吗?
      

  13.   

    自己回答,可以设置,就是在后台使用executeNonQuery()执行"set xact_abort on"语句就行了,
      

  14.   

    2005联机丛书
    ---------------------------
    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 的设置是在执行或运行时设置,而不是在分析时设置。