Sql-server – Unusual deadlock occuring

deadlockdeadlock-graphperformancesql server

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

Best Answer

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