首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >在存储过程中使用"SET XACT_ABORT ON“有什么好处?

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

Stack Overflow用户
提问于 2009-07-19 14:32:40
回答 6查看 162.3K关注 0票数 206

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

EN

回答 6

Stack Overflow用户

回答已采纳

发布于 2009-07-19 14:54:27

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

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

丹·古兹曼的博客上有一个非常好的概述,

票数 276
EN

Stack Overflow用户

发布于 2009-07-19 17:12:56

在我看来,通过在SQL2k5中添加BEGIN /BEGIN,SET XACT_ABORT就过时了。在Transact-SQL中的异常块之前,确实很难处理错误,不平衡的过程非常常见(与entry相比,出口处有一个不同的@@TRANCOUNT )。

通过添加Transact-SQL异常处理,可以更容易地编写正确的过程,从而保证事务之间的平衡。例如,我使用这个异常处理和嵌套事务的模板

代码语言:javascript
运行
复制
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处于打开状态,那么所有这些错误都会导致整个事务丢失,而不是能够编写处理异常的异常块。一个典型的例子是尝试进行插入并恢复到对PK违规的更新。

票数 38
EN

Stack Overflow用户

发布于 2009-07-19 18:33:10

引用MSDN

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

在实践中,这意味着有些语句可能会失败,使事务“部分完成”,而调用方可能没有此失败的迹象。

一个简单的例子:

代码语言:javascript
运行
复制
INSERT INTO t1 VALUES (1/0)    
INSERT INTO t2 VALUES (1/1)    
SELECT 'Everything is fine'

此代码将在关闭XACT_ABORT的情况下执行“成功”,并将以XACT_ABORT ON的错误终止(“插入到t2”将不会被执行,客户端应用程序将引发异常)。

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

票数 24
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/1150032

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档