patternsqlModerate
In what cases a transaction can be committed from inside the CATCH block when XACT_ABORT is set to ON?
Viewed 0 times
canthecommittedwhatxact_abortblockcatchtransactionwheninside
Problem
I've been reading MSDN about
It has the following example that uses
What I don't understand is, why should I care and check what
Please note, that the flag
If there is a severe enough error inside the
But, this example from MSDN implies that there ca
TRY...CATCH and XACT_STATE. It has the following example that uses
XACT_STATE in the CATCH block of a TRY…CATCH construct to determine whether to commit or roll back a transaction: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;
GOWhat I don't understand is, why should I care and check what
XACT_STATE returns?Please note, that the flag
XACT_ABORT is set to ON in the example.If there is a severe enough error inside the
TRY block, the control will pass into CATCH. So, if I'm inside the CATCH, I know that transaction has had a problem and really the only sensible thing to do in this case is to roll it back, isn't it?But, this example from MSDN implies that there ca
Solution
It turns out that transaction can not be committed from inside the
The example from MSDN is somewhat misleading, because the check implies that
It is not true,
It seems that the MSDN sample code was meant to primarily illustrate the use of
The sample code looks generic enough to work with both
It is just that with
There is a very good detailed set of articles about Error and Transaction Handling in SQL Server by Erland Sommarskog.
In Part 2 - Classification of Errors he presents a comprehensive table
that puts together all classes of errors and how they are handled by SQL Server and how
The last column in the table answers the question. With
One note outside the scope of the question. As Erland says, this consistency is one of the reasons to set
I have already given the recommendation that your stored procedures
should include the command
at the table above, you see that with
some higher level of consistency. For instance, the transaction is
always doomed. In the following, I will show many examples where I
set
you should avoid this default setting.
CATCH block if XACT_ABORT is set to ON.The example from MSDN is somewhat misleading, because the check implies that
XACT_STATE can return 1 in some cases and it may be possible to COMMIT the transaction.IF (XACT_STATE()) = 1
BEGIN
PRINT 'The transaction is committable.' +
' Committing transaction.'
COMMIT TRANSACTION;
END;It is not true,
XACT_STATE will never return 1 inside CATCH block if XACT_ABORT is set to ON.It seems that the MSDN sample code was meant to primarily illustrate the use of
XACT_STATE() function regardless of the XACT_ABORT setting.The sample code looks generic enough to work with both
XACT_ABORT set to ON and OFF.It is just that with
XACT_ABORT = ON the check IF (XACT_STATE()) = 1 becomes unnecessary.There is a very good detailed set of articles about Error and Transaction Handling in SQL Server by Erland Sommarskog.
In Part 2 - Classification of Errors he presents a comprehensive table
that puts together all classes of errors and how they are handled by SQL Server and how
TRY ... CATCH and XACT_ABORT changes the behaviour.+-----------------------------+---------------------------++------------------------------+
| | Without TRY-CATCH || With TRY-CATCH |
+-----------------------------+-------+-------+-----+-----++------------------+-----+-----+
| SET XACT_ABORT | OFF | ON | OFF | ON || ON or OFF | OFF | ON |
+-----------------------------+-------+-------+-----+-----++------------------+-----+-----+
| Class Name | Aborts | Rolls || Catchable | Dooms |
| | | Back || |transaction|
+-----------------------------+-------+-------+-----+-----++------------------+-----+-----+
| Fatal errors | Connection | Yes || No | n/a |
| Batch-aborting | Batch | Yes || Yes | Yes |
| Batch-only aborting | Batch | No | Yes || Yes | No | Yes |
| Statement-terminating | Stmnt | Batch | No | Yes || Yes | No | Yes |
| Terminates nothing at all | Nothing | No || Yes | No | Yes |
| Compilation: syntax errors | (Statement) | No || Yes | No | Yes |
| Compilation: binding errors | Scope | Batch | No | Yes || Outer scope only | No | Yes |
| Compilation: optimisation | Batch | Yes || Outer scope only | Yes |
| Attention signal | Batch | No | Yes || No | n/a |
| Informational/warning msgs | Nothing | No || No | n/a |
| Uncatchable errors | Varying | Varying || No | n/a |
+-----------------------------+-------+-------+-----+-----++------------------+-----+-----+
The last column in the table answers the question. With
TRY-CATCH and with XACT_ABORT ON the transaction is doomed in all possible cases.One note outside the scope of the question. As Erland says, this consistency is one of the reasons to set
XACT_ABORT to ON:I have already given the recommendation that your stored procedures
should include the command
SET XACT_ABORT, NOCOUNT ON. If you lookat the table above, you see that with
XACT_ABORT in effect, there issome higher level of consistency. For instance, the transaction is
always doomed. In the following, I will show many examples where I
set
XACT_ABORT to OFF, so that you can get an understanding of whyyou should avoid this default setting.
Code Snippets
IF (XACT_STATE()) = 1
BEGIN
PRINT 'The transaction is committable.' +
' Committing transaction.'
COMMIT TRANSACTION;
END;Context
StackExchange Database Administrators Q#128535, answer score: 12
Revisions (0)
No revisions yet.