Nếu bạn có khối TRY / CATCH thì nguyên nhân có thể là bạn đang bắt một ngoại lệ hủy bỏ giao dịch và tiếp tục. Trong khối CATCH, bạn phải luôn kiểm tra XACT_STATE()
và xử lý các giao dịch bị hủy bỏ và không thể chấp nhận (bị hủy bỏ) thích hợp. Nếu người gọi của bạn bắt đầu một giao dịch và lịch trình xảy ra, chẳng hạn như bế tắc (đã hủy bỏ giao dịch), làm thế nào người gọi sẽ thông báo với người gọi rằng giao dịch đã bị hủy bỏ và nó sẽ không tiếp tục với 'hoạt động kinh doanh như bình thường'? Cách khả thi duy nhất là nâng lại một ngoại lệ, buộc người gọi phải xử lý tình huống. Nếu bạn âm thầm nuốt một giao dịch đã hủy bỏ và người gọi tiếp tục giả sử vẫn còn trong giao dịch ban đầu, chỉ có thể đảm bảo tình trạng lộn xộn (và lỗi bạn nhận được là cách động cơ cố gắng bảo vệ chính nó).
Tôi khuyên bạn nên xem qua Xử lý ngoại lệ và các giao dịch lồng nhau cho thấy một mẫu có thể được sử dụng với các giao dịch và ngoại lệ lồng nhau:
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