Jika Anda memiliki blok TRY/CATCH maka kemungkinan penyebabnya adalah Anda menangkap pengecualian pembatalan transaksi dan melanjutkan. Di blok CATCH Anda harus selalu memeriksa XACT_STATE()
dan menangani transaksi yang dibatalkan dan tidak dapat dilakukan (dihukum) yang sesuai. Jika penelepon Anda memulai transaksi dan calee mencapai, katakanlah, kebuntuan (yang membatalkan transaksi), bagaimana callee akan mengomunikasikan kepada penelepon bahwa transaksi dibatalkan dan tidak boleh dilanjutkan dengan 'bisnis seperti biasa'? Satu-satunya cara yang layak adalah dengan memunculkan kembali pengecualian, memaksa penelepon untuk menangani situasi tersebut. Jika Anda diam-diam menelan transaksi yang dibatalkan dan penelepon melanjutkan dengan asumsi masih dalam transaksi asli, hanya kekacauan yang dapat memastikan (dan kesalahan yang Anda dapatkan adalah cara mesin mencoba melindungi dirinya sendiri).
Saya sarankan Anda membaca Penanganan pengecualian dan transaksi bertingkat yang menunjukkan pola yang dapat digunakan dengan transaksi dan pengecualian bersarang:
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