По моему мнению, SET XACT_ABORT ON устарел благодаря добавлению BEGIN TRY / BEGIN CATCH в SQL 2k5. До блоков исключений в Transact-SQL было действительно трудно обрабатывать ошибки, и несбалансированные процедуры были слишком распространены (процедуры, которые имели различный @@ 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 включен, то все эти ошибки приводят к потере всей транзакции, в отличие от возможности кодировать блоки исключений, которые корректно обрабатывают исключение. Типичный пример - попытка сделать INSERT и возврат к UPDATE при нарушении PK.