UPDATE锁如何防止常见形式的死锁?

时间:2014-03-12 13:39:43

标签: sql-server sql-server-2008-r2

SQL Server books online表示UPDATE锁可以防止常见的死锁形式:

  

更新锁定

     

更新(U)锁可以防止常见的死锁形式。

它们如何防止常见形式的死锁?

我的意思是什么?

一种常见的死锁形式是当两个进程尝试从共享(S)锁(即读锁)升级到Exclusive(X)锁时:

Process A                       Process B
========================        ========================
Acquire Shared lock
                                Acquire Shared lock
Attempt to escalate to X
Escalation waits on B 
                                Attempt to escalate to X
                                Escalation waits on A

死锁 的。两个进程都在等待。

这一点在BOL中有所解释:

  

典型的更新模式包括读取记录的事务,获取资源(页面或行)上的共享(S)锁,然后修改行,这需要锁转换为独占(X)锁。如果两个事务获取资源上的共享模式锁,然后尝试同时更新数据,则一个事务会尝试将锁转换为独占(X)锁。共享模式到独占锁定转换必须等待,因为一个事务的独占锁定与另一个事务的共享模式锁定不兼容;锁定等待发生。第二个事务尝试获取其更新的独占(X)锁。因为两个事务都转换为独占(X)锁,并且它们都在等待另一个事务释放其共享模式锁,所以会发生死锁。

使用更新锁来防止死锁

联机丛书没有解释更新(U)锁如何防止这种常见形式的死锁,他们所说的只是:

  

为避免此潜在的死锁问题,使用更新(U)锁。一次只有一个事务可以获得对资源的更新(U)锁定。如果事务修改资源,则更新(U)锁将转换为独占(X)锁。否则,锁将转换为共享模式锁。

描述不完整。如果您查看短语"只有一个事务可以一次获得对资源的更新(U)锁定" 。这与独占(X)锁没有什么不同 - 只有一个事务可以在一次获得对资源的独占(X)锁。但是让我们试着弄清楚:

首先我们假设是正常的更新过程:

  • 获取共享(S)锁
  • 尝试升级以更新(U)锁定
  • 执行更新
  • 需要更改值,升级到独占(X)锁定
  • 升级至独家(X)锁定
  • 执行更新
  • 释放所有锁

现在添加第二个流程

Process A                       Process B
========================        ========================
Acquire Shared lock
                                Acquire Shared lock
Attempt to escalate to U
Escalation waits on B 
                                Attempt to escalate to U
                                Escalation waits on A

死锁 的。两个进程都在等待。

更新(U)锁如何防止常见形式的死锁?

2 个答案:

答案 0 :(得分:6)

  

描述不完整。如果你看一下短语"只有一个   事务可以一次获得对资源的更新(U)锁定"。   这与独占(X)锁定没有区别 - 只有一个事务   可以在时间获得对资源的独占(X)锁定。

U锁与S锁兼容,而X锁不是这种情况。这意味着在确定要写入的行时(使用U锁),仍然允许其他读取器。

  

所以现在添加第二个过程......

这里的误解是,作家从S升级到U.事实并非如此。他们从一开始就使用U.它们稍后从U升级到X,但在这种情况下对死锁没有任何意义。

为了更清楚地说明这一点:让我们假设我们运行以下语句:

UPDATE T SET SomeCol = 1 WHERE (ID BETWEEN 1 AND 2) AND (SomeOtherCond = 1)

假设这是使用ID上的聚簇索引上的范围扫描执行的,并且SomeOtherCond = 1仅对行ID = 2为真。这将为您获取两行的U锁,并为ID = 2的行升级到X.行ID = 2的U锁定将提前释放。

答案 1 :(得分:2)

更新锁用于查找要更新的行,因此由DELETE和UPDATE语句使用。找到Update的行后,锁将转换为X锁。

请参阅Kalen Delany Blog