在存储过程中使用SET XACT_ABORT ON
有什么好处?
发布于 2009-07-19 14:54:27
SET XACT_ABORT ON
指示Server回滚整个事务,并在发生运行时错误时中止批处理。它在客户端应用程序上而不是在Server本身(默认的XACT_ABORT OFF
设置没有涵盖)等情况下涵盖了您。
由于查询超时将使事务处于打开状态,因此建议在所有具有显式事务的存储过程中使用SET XACT_ABORT ON
(除非您有特定的理由不这样做),因为应用程序执行与打开的事务连接的工作的后果是灾难性的。
在丹·古兹曼的博客上有一个非常好的概述,
发布于 2009-07-19 17:12:56
在我看来,通过在SQL2k5中添加BEGIN /BEGIN,SET XACT_ABORT就过时了。在Transact-SQL中的异常块之前,确实很难处理错误,不平衡的过程非常常见(与entry相比,出口处有一个不同的@@TRANCOUNT )。
通过添加Transact-SQL异常处理,可以更容易地编写正确的过程,从而保证事务之间的平衡。例如,我使用这个异常处理和嵌套事务的模板
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违规的更新。
发布于 2009-07-19 18:33:10
引用MSDN
当SET XACT_ABORT打开时,如果Transact-SQL语句引发运行时错误,则整个事务将终止并回滚。当SET XACT_ABORT关闭时,在某些情况下只回滚引发错误的Transact-SQL语句,事务继续处理。
在实践中,这意味着有些语句可能会失败,使事务“部分完成”,而调用方可能没有此失败的迹象。
一个简单的例子:
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。
https://stackoverflow.com/questions/1150032
复制相似问题