TRY / CATCHブロックがある場合、考えられる原因は、トランザクションアボート例外をキャッチして続行していることです。CATCHブロックでは、常にを確認しXACT_STATE()
、適切に中止されコミットできない(終了した)トランザクションを処理する必要があります。呼び出し元がトランザクションを開始し、caleeが(トランザクションを中止した)デッドロックにヒットした場合、呼び出し先は、トランザクションが中止され、「通常どおりのビジネス」を続行すべきでないことを呼び出し元にどのように伝えますか?実行可能な唯一の方法は、例外を再度発生させ、呼び出し側に状況を処理させることです。中止されたトランザクションを黙って飲み込み、呼び出し元がまだ元のトランザクションにいると想定し続ける場合、確認できるのは騒乱だけです(そして、エラーは、エンジンがそれ自体を保護しようとする方法です)。
ネストされたトランザクションと例外で使用できるパターンを示す例外処理とネストされたトランザクションを検討することをお勧めします。
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