Unusual deadlock occuring
-
18-02-2021 - |
Question
I have spent a few days trying to debug a deadlock that occurs in production. This is one I didn't understand however. Below is pseudo code for the stored procedure. The stored procedure generates a deadlock with another instance of itself.
I know that the code is not brilliant, this old code on the system. But I want to understand why this deadlocks. The graph always shows the second selects deadlocking.
The first select performs a table scan, so I believe that places click on all rows in table.
I'd have thought this would queue one stored procedure behind the other. I cannot recreate this after days if trying.
Begin tran
Begin tran
Set isolation level repeatable read
//This select does a table scan, so I believe does X lock on all rows
Select a,b,c
From queuetable with(xlock, rowlock)
Where a = x
Delete from queuetable
Where a = X
Commit tran
Begin tran
//Get oldest row - this is the deadlocking query
Select top 1 a,b,c
From queuetable
Order by b
//Mark row to be processed
Update queuetable
Set c=processing
Where a = y
Commit tran
Commit tran
No correct solution
OTHER TIPS
Try without the first BEGIN TRAN and last COMMIT TRAN.
If you are using a stored procedure, the procedure itself already creates a transaction.
Your transaction locks because of the following script:
//This select does a table scan, so I believe does X lock on all rows
Select a,b,c
From queuetable with(xlock, rowlock)
Where a = x
From what I see in the script, the with(xlock, rowlock)
is not needed.
Try with the following script:
SET XACT_ABORT ON
SET ISOLATION LEVEL REPEATABLE READ
-- This select does a table scan, so I believe does X lock on all rows
SELECT a, b, c
FROM queuetable
WHERE a = x
DELETE queuetable
WHERE a = X
-- Get oldest row - this is the deallocking query
SELECT TOP 1 a, b, c
FROM queuetable
ORDER BY b
-- Mark row to be processed
UPDATE queuetable
SET c = processing
WHERE a = y