Why is the lock on the key not held?

35 Views Asked by At

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.

Mine looks like this: Locks

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?

0

There are 0 best solutions below