Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

TransactionAbortedException - can you safely re-run?

Tags:

c#

sql-server

I am using TransactionScope in the following fashion

using (var scope = new TransactionScope())
{
    using (var conn = SQLHelpers.GetSQLConnection())
    {  
          //commands here
    }
    scope.Complete();
}

Sometimes I am getting an TransactionAbortedException when calling scope.Complete() as the transaction has already been rolled back and I have used the profiler to determine the issue is a deadlock.

Exception Transaction (Process ID 59) was deadlocked on lock resources with another process and has been chosen as the deadlock victim. Rerun the transaction.

I've since found the cause for the deadlock however it got me wondering why this error did not bubble up to the TransactionAbortedException so I could indeed re-run the transaction just for that specific case. The inner exception(s) did NOT contain any information that could indicate what the actual error was.

Is it safe to detect a TransactionAbortedException as the reason to re-run the transaction?

Up to now I've seen the following inner exceptions:

1) deadlock
2) timeout
3) 'connection was closed'
4) .. other ?

in only 1 of these cases it seems appropriate to re-run the transaction however you could generalize this to all cases if you were guaranteed a rollback. The question could be re-stated to ask 'does a TransactionAbortedException guarantee the transaction was rolled back' ?

like image 932
wal Avatar asked Oct 21 '16 05:10

wal


1 Answers

The question could be re-stated to ask 'does a TransactionAbortedException guarantee the transaction was rolled back'?

The documentation for TransactionAbortedException says:

This exception is thrown when an action is attempted on a transaction that has already been rolled back, for example, when you attempt to call the Commit method on a transaction that has already timed out. This exception is also thrown when an attempt is made to commit the transaction and the transaction aborts.

This is a recoverable error.

I think it is pretty clear from this description that if you catch this exception, your transaction didn't complete successfully due to some reason. My understanding of the docs is: "Whatever changes the transaction was trying to do were not committed to the database".

"This is a recoverable error", so if the nature of your transaction is such that it makes sense to retry it, then you should retry it after catching this exception.

You may want to introduce some logic around retries, such as waiting for some time before retry. And increase this waiting time as the number of retry attempts increases. Have a limit on the total amount of retries or total retry time and do something sensible/fail gracefully when all attempts to retry failed.

like image 65
Vladimir Baranov Avatar answered Nov 04 '22 16:11

Vladimir Baranov