当前位置:网站首页>Deadlock caused by non clustered index in SQL Server

Deadlock caused by non clustered index in SQL Server

2022-07-07 10:05:00 knight_ hf

Recently, a message sending function encountered a deadlock problem caused by non clustered indexes during the test , The following is what my partner summarized afterwards , Now share it .
( Because some content involves company information , So I only shared some of them , But it should not affect the overall reading )

Situation introduction

Table name is Receiver, Field has id( Primary key , Clustered index ),msgId( Nonclustered indexes ),receiver( Nonclustered indexes ),createTime,updateTime

The statements executed concurrently are

1、insert into Receiver select msgId,receiver,createTime,updateTime from tempTable 2update Receiver set updateTime=#{} where msgId=#{} and receiver in (#{})

Occurrence scenario

1、 Multithreading (100 individual ) perform Receiver Insert statement of
2、 Multithreading (8 Threads ) perform Receiver UPDATE statement of

Lock analysis

1、insert Statement execution time , First apply for the line where the record is inserted ( Or page 、 surface ) Of X lock ( Exclusive lock ), After record insertion , Applying for non clustered indexes X lock , Finish updating the index , When it's all done , Release what is held X lock
2、update Statement execution time , apply msgId In a nonclustered index U lock , adopt msgId The non clustered index gets the location of the record that needs to be updated , Then apply for the clustered index of the corresponding record U lock ( Update lock ), Because it does not involve the update of nonclustered indexes , So after the data update , all U The lock is released

Deadlock analysis

Let's first assume insert priority ,insert Successfully apply to the row with inserted data X lock , Because multiple records are inserted at one time , So the actual application is to aggregate index pages pagelock. After record insertion ,insert The process will apply msgId、updateTime Nonclustered index X lock . Suppose this time insert The process is suspended , The right of execution is given to update process .update Priority application msgId Nonclustered index U Lock to query the set of records that need to be updated , After finding the corresponding record , I will apply for these records U lock ( The same is pagelock). But because this data page has been insert The process adds X lock , So we can't add U lock , therefore update The process enters a waiting state . meanwhile ,insert The process also needs to apply for indexing X lock , But it has been update The process holds U lock . Last , The two processes enter the state of waiting for each other , A deadlock occurs .

What happened

1、 In the case of high concurrency update And insert
2、update Of where The non clustered index of the table is used in the condition

terms of settlement

modify update sentence
The original statement is

update Receiver set updateTime=#{
   } where msgId=#{
   } and receiver in (#{
   })

1、 Add row level lock

update Receiver with(rowlock) set updateTime=#{
   } where msgId=#{
   } and receiver in (#{
   })

After changing to row level lock , Can significantly reduce insert Requested lock and update The requested lock coincides
Inferiority : When updating multiple records, multiple row level locks will be held , Previously, it was possible to hold only one page lock
2、where Add with(nolock)

update Receiver set updateTime=#{} where id in (select r.id from Receiver r with(nolock) where r.msgId=#{} and r.receiver in (#{}))
原网站

版权声明
本文为[knight_ hf]所创,转载请带上原文链接,感谢
https://yzsam.com/2022/02/202202130623569660.html