在存储过程中使用“SET XACT_ABORT ON”有什么好处?

时间:2009-07-19 14:32:40

标签: sql sql-server

在存储过程中使用 SET XACT_ABORT ON 有什么好处?

6 个答案:

答案 0 :(得分:202)

SET XACT_ABORT ON指示SQL Server回滚整个事务,并在发生运行时错误时中止批处理。它涵盖了客户端应用程序上发生的命令超时而不是SQL Server本身(默认XACT_ABORT OFF设置未涵盖的情况)。

由于查询超时将使事务保持打开状态,因此建议在具有显式事务的所有存储过程中使用SET XACT_ABORT ON(除非您有特定的理由不这样做)作为应用程序在与公开交易是灾难性的。

Dan Guzman's Blog

有一个很好的概述

答案 1 :(得分:31)

在我看来,SET XACT_ABORT ON在SQL 2k5中添加了BEGIN TRY / BEGIN CATCH已经过时了。在Transact-SQL中的异常块之前,处理错误非常困难,并且不平衡的过程非常常见(与入口相比,退出时具有不同的@@ TRANCOUNT的过程)。

通过添加Transact-SQL异常处理,可以更容易地编写保证正确平衡事务的正确过程。例如,我使用此template for exception handling and nested transactions

create procedure [usp_my_procedure_name]
as
begin
    set nocount on;
    declare @trancount int;
    set @trancount = @@trancount;
    begin try
        if @trancount = 0
            begin transaction
        else
            save transaction usp_my_procedure_name;

        -- Do the actual work here

lbexit:
        if @trancount = 0   
            commit;
    end try
    begin catch
        declare @error int, @message varchar(4000), @xstate int;
        select @error = ERROR_NUMBER(), @message = ERROR_MESSAGE(), @xstate = XACT_STATE();
        if @xstate = -1
            rollback;
        if @xstate = 1 and @trancount = 0
            rollback
        if @xstate = 1 and @trancount > 0
            rollback transaction usp_my_procedure_name;

        raiserror ('usp_my_procedure_name: %d: %s', 16, 1, @error, @message) ;
    end catch   
end
go

它允许我编写原子过程,在可恢复错误的情况下只回滚自己的工作。

Transact-SQL程序面临的主要问题之一是数据纯度:有时收到的参数或表中的数据都是完全错误的,导致重复的键错误,参考约束错误,检查约束错误等等。毕竟,这正是这些约束的作用,如果这些数据纯度错误是不可能的并且都被业务逻辑所捕获,则约束将全部过时(为效果添加了戏剧性的夸张)。如果XACT_ABORT为ON,则所有这些错误都会导致整个事务丢失,而不能正常编写处理异常的异常块。一个典型的例子是尝试执行INSERT并在PK违规时恢复为UPDATE。

答案 2 :(得分:20)

引用MSDN

  

当SET XACT_ABORT为ON时,如果Transact-SQL语句引发运行时错误,则终止并回滚整个事务。   当SET XACT_ABORT为OFF时,在某些情况下,只会回滚引发错误的Transact-SQL语句,并且事务将继续处理。

实际上,这意味着某些语句可能会失败,导致事务“部分完成”,并且调用者可能没有这种失败的迹象。

一个简单的例子:

INSERT INTO t1 VALUES (1/0)    
INSERT INTO t2 VALUES (1/1)    
SELECT 'Everything is fine'

此代码将在XACT_ABORT OFF时“成功”执行,并在XACT_ABORT ON时出现错误(“INSERT INTO t2”将不会执行,客户端应用程序将引发异常)。

作为一种更灵活的方法,您可以在每个语句(旧学校)之后检查@@ ERROR,或使用TRY ... CATCH块(MSSQL2005 +)。我个人更喜欢在没有理由进行某些高级错误处理时设置XACT_ABORT。

答案 3 :(得分:4)

关于客户端超时和使用XACT_ABORT来处理它们,在我看来,至少有一个很好的理由在客户端API(如SqlClient)中有超时,那就是保护客户端应用程序代码免受SQL Server中发生的死锁码。在这种情况下,客户端代码没有故障,但必须保护自己不会阻止永远等待命令在服务器上完成。相反,如果必须存在客户端超时以保护客户端代码,那么XACT_ABORT ON必须保护服务器代码免受客户端中止,以防服务器代码执行的时间比客户端愿意等待的时间长。

答案 4 :(得分:1)

它用于事务管理,以确保任何错误都会导致事务回滚。

答案 5 :(得分:0)

XACT_ABORT ON 监视事务的状态。如果 XACT_STATE =-1,则事务中发生错误。如果 XACT_STATE=1,则事务完成。如果 XACT_State=0,则没有打开的事务。 XACT_ABORT 指定当前事务发生错误时是否自动回滚。

相关问题