Wykorzystanie XACT_STATE do sprawdzenia stanu transakcji

17-lis-2012

Poniższy przykład pochodzi z http://msdn.microsoft.com/en-us/library/ms189797.aspx.  Prezentuje on, jak można dobrze wykonywać transakcje i reagować na potencjalnie pojawiające się błędy.

1. Po pierwsze używaj opcji SET XACT_ABORT ON. Powoduje ona „awansowanie błędów” powodujących przerwanie pojedynczego STATEMENT na błędy powodujące przerwanie batcha, lub przejście do bloku CATCH w przypadku obsługi błędów poprzez TRY/CATCH

2 Używaj TRY/CATCH do wychwycenia błędów. Jeżeli twoja transakcja składa się z wielu instrukcji, to transakcja sama w sobie nie wycofa wszystkiego po napotkaniu pierwszego lepszego błędu (chyba że użyłeś XACT_ABORT). To do Ciebie należy obsługa tego błędu

3. Używaj wartości funkcji XACT_STATE() do oceny tego co można zrobić dalej:

  • 1 masz otwartą transakcję i nadaje się ona do commitowania
  • 0  nie ma otwartej transakcji. Zarówno commit jak i rollback spowodowały by błędy
  • -1 masz otwartą transakcję, ale nie da się jej skommitować. Np. próbowałeś wstawić duplikujący się rekord na kolumnie z CONSTRAINT UNIQUE. Zrób co chcesz, a potem wywołaj rollback do tej transakcji.

Wszystko ładnie widać na poniższym przykładzie:

USE AdventureWorks2012;
GO

— SET XACT_ABORT ON will render the transaction uncommittable
— when the constraint violation occurs.
SET XACT_ABORT ON;

BEGIN TRY
BEGIN TRANSACTION;
— A FOREIGN KEY constraint exists on this table. This
— statement will generate a constraint violation error.
DELETE FROM Production.Product
WHERE ProductID = 980;

— If the delete operation succeeds, commit the transaction. The CATCH
— block will not execute.
COMMIT TRANSACTION;
END TRY
BEGIN CATCH
— Test XACT_STATE for 0, 1, or -1.
— If 1, the transaction is committable.
— If -1, the transaction is uncommittable and should
—     be rolled back.
— XACT_STATE = 0 means there is no transaction and
—     a commit or rollback operation would generate an error.

— Test whether the transaction is uncommittable.
IF (XACT_STATE()) = -1
BEGIN
PRINT 'The transaction is in an uncommittable state.’ +
’ Rolling back transaction.’
ROLLBACK TRANSACTION;
END;

— Test whether the transaction is active and valid.
IF (XACT_STATE()) = 1
BEGIN
PRINT 'The transaction is committable.’ +
’ Committing transaction.’
COMMIT TRANSACTION;
END;
END CATCH;
GO

Komentarze są wyłączone

Autor: Rafał Kraik