SQL Serverジョブの各ステップにはDML操作があります。何かがうまくいかない場合に更新/挿入が確実にロールバックされるようにするために、私は各ステップのデータ変更をTRY CATCH
およびTRANSACTION
ブロックにラップしました:
BEGIN TRY
BEGIN TRANSACTION
[[INSERT/update statements]] ...
IF @@TRANCOUNT > 0
BEGIN
COMMIT TRANSACTION
PRINT 'Successful.'
END
END TRY
BEGIN CATCH
SELECT
ERROR_NUMBER() AS ErrorNumber,
ERROR_SEVERITY() AS ErrorSeverity,
ERROR_STATE() AS ErrorState,
ERROR_PROCEDURE() AS ErrorProcedure,
ERROR_LINE() AS ErrorLine,
ERROR_MESSAGE() AS ErrorMessage
IF @@TRANCOUNT > 0
BEGIN
ROLLBACK TRANSACTION
PRINT 'Unsuccessful.'
END
END CATCH
エラーが発生した場合、データ操作が確実にロールバックされますか?または他の考慮事項を考慮する必要がありますか?
(構成などを使用して)それを行うより良い方法はありますか?
ありがとうございました。
例外処理とネストされたトランザクション のようなパターンをお勧めします。
_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
_
このパターンは、catchブロックの XACT_STATE()
をチェックして、 コミットできないトランザクション から保護します。
コミットできないトランザクションとXACT_STATE
TRYブロックで生成されたエラーにより現在のトランザクションの状態が無効になる場合、そのトランザクションはコミットできないトランザクションとして分類されます。通常、TRYブロックの外部でトランザクションを終了するエラーが発生すると、TRYブロックの内部でエラーが発生すると、トランザクションがコミットできない状態になります。コミットできないトランザクションは、読み取り操作またはROLLBACK TRANSACTIONのみを実行できます。トランザクションは、書き込み操作またはCOMMIT TRANSACTIONを生成するTransact-SQLステートメントを実行できません。トランザクションがコミットできないトランザクションとして分類されている場合、XACT_STATE関数は値-1を返します。バッチが終了すると、データベースエンジンはアクティブなコミットできないトランザクションをロールバックします。トランザクションがコミットできない状態になったときにエラーメッセージが送信されなかった場合、バッチが完了すると、エラーメッセージがクライアントアプリケーションに送信されます。これは、コミットできないトランザクションが検出され、ロールバックされたことを示しています。
あなたのコードは、0にできない場所で_@@TRANCOUNT
_をチェックしています。成功を通知するために、情報を提供するPRINTメッセージとSELECT結果セットの混合を使用し、回復可能なエラーを処理しません。理想的には、例外はクライアント、この場合はエージェントジョブに伝播する必要があります(つまり、キャッチは再発生するはずです)。
あなたが持っているものは私にはよさそうだ。もちろん、トランザクションをロールバックした後で、その情報を使用して何かを行うことをお勧めします。ログに書き込みます。