在存储过程中使用 SET XACT_ABORT ON
有什么好处?
答案 0 :(得分:202)
SET XACT_ABORT ON
指示SQL Server回滚整个事务,并在发生运行时错误时中止批处理。它涵盖了客户端应用程序上发生的命令超时而不是SQL Server本身(默认XACT_ABORT OFF
设置未涵盖的情况)。
由于查询超时将使事务保持打开状态,因此建议在具有显式事务的所有存储过程中使用SET XACT_ABORT ON
(除非您有特定的理由不这样做)作为应用程序在与公开交易是灾难性的。
答案 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 指定当前事务发生错误时是否自动回滚。