Ian*_*oyd 6 sql-server sql-server-2008-r2
在SQL服务器联机丛书说,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
Run Code Online (Sandbox Code Playgroud)
死锁.两个进程都在等待.
这一点在BOL中都有解释:
典型的更新模式包括读取记录的事务,获取资源(页面或行)上的共享(S)锁,然后修改行,这需要锁转换为独占(X)锁.如果两个事务获取资源上的共享模式锁,然后尝试同时更新数据,则一个事务会尝试将锁转换为独占(X)锁.共享模式到独占锁定转换必须等待,因为一个事务的独占锁定与另一个事务的共享模式锁定不兼容; 锁定等待发生.第二个事务尝试获取其更新的独占(X)锁.因为两个事务都转换为独占(X)锁,并且它们都在等待另一个事务释放其共享模式锁,所以会发生死锁.
联机丛书没有解释更新(U)锁如何防止这种常见形式的死锁,他们所说的只是:
为避免此潜在的死锁问题,使用更新(U)锁.一次只有一个事务可以获得对资源的更新(U)锁定.如果事务修改资源,则更新(U)锁将转换为独占(X)锁.否则,锁将转换为共享模式锁.
描述不完整.如果您查看短语"一次只能有一个事务可以获取对资源的更新(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
Run Code Online (Sandbox Code Playgroud)
死锁.两个进程都在等待.
更新(U)锁如何防止常见形式的死锁?
描述不完整.如果您查看短语"一次只能有一个事务可以获取对资源的更新(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)
Run Code Online (Sandbox Code Playgroud)
假设这是在聚集索引上使用范围扫描执行的ID,并且SomeOtherCond = 1仅对该行执行ID = 2.这将让你的U锁两行,并升级到X与行ID = 2.行的U形锁ID = 2将提前释放.
| 归档时间: |
|
| 查看次数: |
2438 次 |
| 最近记录: |