When analyzing a locking error in SQL Server I found a design decision which causes deadlocks. I want to understand why this decision was made. As for context: If somebody updates a table I have a trigger that writes the username in the table. That is why in session 1 there is a second update in the same transaction.
Below I describe how you can provoke the deadlock and show the locks held by the processes. Then I will detail the question.
First, open three sessions in SQL Server and copy the below code in.
--Session 1
create table ##tTestTable
(ID int
, Wert varchar(max)
, [User] varchar(max) null)
Select *
From ##tTestTable
insert into ##tTestTable
Select 1, 'A', null
insert into ##tTestTable
Select 2, 'A', null
create index TestIndex on ##tTestTable (ID)
Begin transaction
Select @@SPID as FirstTransactionProcessID
Update ##tTestTable --with (holdlock)
Set Wert = 'B'
where ID in (1)
--Stop here and start session 2
Update ##tTestTable
set [User] = SYSTEM_USER
where ID in (1)
commit
--Session 2
Begin transaction
Select @@SPID as FirstTransactionProcessID
Update ##tTestTable
Set Wert = 'C'
where ID in (1)
commit
--Session 3
exec sp_lock
Now execute everything in session one up to the comment that says "stop". Then execute session 2 and have a look at the locks with session 3.
Process 64 is session 1 and 69 is session 2.
As you can see session 1 holds an X lock on row 7:184:0. Session 2 would like to have a U lock on that row but since U and X are incompatible it has to wait. However, session 2 holds a U lock on the key. Now if you execute the second part of session 1 it would also like to have a u lock on the key. Session 1 waits for session 2 and vice versa. The SQL server detects the deadlock and kills session 2.
I changed the ID in session 2 to 2 to check whether the key is one big thing or divided by ID. When doing the test no deadlock occured.
My takeaway: The keylock and the rowlock lock are the exact same row. But when the first update of session 1 resolves it lifts the U lock off the key and keeps an X lock on the row.
Wouldn't it always be better for session 1 to keep the U lock on the key to avoid this deadlock situation? Does somebody have one good example why it makes sense to lift the U lock?
