我仍在对这个问题中提到的死锁进行故障排除。在这方面,我得到了帮助,理解了为什么 select 会持有共享锁,并且我也能够测试并确认这一点。
现在我正在查看陷入僵局的第二个 spid。该会话使用主键进行更新(WHERE BatchId = @BatchI,BatchId 是 PK)并且它需要在两个页面上使用 IX。最初我不明白为什么它只更新一行时需要锁定非聚集索引的两页。然后我意识到对该行的更新将更改该行在非聚集索引中的位置,这可能是它需要在两个页面上锁定的原因。
那是对的吗?
其次,请帮助确认我对这个僵局的理解是正确的。为简单起见,我们假设该非聚集索引中只有两个页面。第 1 页和第 2 页。这就是正在发生的事情吗
一些测试也是如此,死锁实际上是由非聚集索引内的页面移动引起的,该更新是由更改行在索引中的位置的更新引起的。
所以最初Session 2(update)在索引行原来所在的Page2上取出了IX锁。由于更新会更改值并进而更改索引行在索引中的位置,因此会话 2 还需要在目标页上获取另一个 IX 锁,索引行将在更新后结束。
要了解 select 想要保留 S 锁的原因,请参阅此问题。
回购协议