From what i undertand it is impossible to completely prevent a transaction from deadlocking.
I would like to have transaction that neverfail from the perpective of application code. So i have seen this pattern in use for Microsoft SQL and I wonder if this is a good idea?
DECLARE @retry tinyint
SET @retry = 5
WHILE @retry >0
BEGIN
BEGIN TRANSACTION
BEGIN TRY
// do transaction her
COMMIT
BREAK
END TRY
BEGIN CATCH
ROLLBACK
if (ERROR_NUMBER() = 1205 OR ERROR_NUMBER() = 1222)
BEGIN
SET @retry = @retry - 1
IF @retry = 0
RAISEERROR('Could not complete transaction',16,1);
WAITFOR DELAY '00:00:00.05' -- Wait for 50 ms
CONTINUE
END
ELSE
BEGIN
RAISEERROR('Non-deadlock condition encountered',16,1);
BREAK;
END
END CATCH;
END
The implementation you have is not a good idea, as it blindly retries without finding out the actual error. If the error was a timeout, for example, you might end up tying up a connection for 5 times the timeout amount, without ever resolving a thing.
A much better approach is to detect that it was Error 1205 - a deadlock victim and retry only in that case.
You can use:
IF ERROR_NUMBER() = 1205
See the documentation for ERROR_NUMBER().
Retry logic for recoverable errors should be in the client code.
For deadlocks, MSDN states to do it there
If you retry in SQL, then you may hit CommandTimeout eventually.
There are other errors too so you can write a generic handler
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With