joj*_*ojo 4 sql-server deadlock locking
我正在阅读了解 SQL Server 中的锁定。但不太明白更新锁的用途。
详细说明如下:
更新锁
更新 (U) 锁可防止常见形式的死锁。典型的更新模式包括事务读取记录、获取资源(页或行)上的共享 (S) 锁,然后修改该行,这需要将锁转换为排他 (X) 锁。如果两个事务获取资源上的共享模式锁,然后尝试同时更新数据,则一个事务会尝试将锁转换为排它 (X) 锁。共享模式到排它锁的转换必须等待,因为一个事务的排它锁与另一个事务的共享模式锁不兼容;发生锁等待。第二个事务尝试为其更新获取独占 (X) 锁。由于两个事务都转换为排它 (X) 锁,并且它们都在等待另一个事务释放其共享模式锁,因此会发生死锁。
为了避免这种潜在的死锁问题,使用更新(U)锁。一次只有一个事务可以获得资源的更新 (U) 锁。如果事务修改资源,则更新 (U) 锁将转换为排他 (X) 锁。否则,锁将转换为共享模式锁。
考虑下面两个事务(两个事务都执行Isolation Level Repeatable Read以在事务期间保持 S 锁):
在 TRAN1 中执行以下 SQL。
BEGIN TRAN
SELECT BrandName FROM dbo.Brand WHERE BrandId=2
Run Code Online (Sandbox Code Playgroud)
现在,TRAN1 为 RID 授予 S 锁
在 TRAN2 中执行以下 SQL
BEGIN TRAN
SELECT BrandName FROM dbo.Brand WHERE BrandId=2
Run Code Online (Sandbox Code Playgroud)
现在,TRAN2 为与 TRAN1 相同的 RID 资源授予 S 锁
在 TRAN1 中执行以下 SQL
UPDATE dbo.Brand SET BrandName='YBrand' WHERE BrandId=2
Run Code Online (Sandbox Code Playgroud)
现在,TRAN1 S锁转换为U锁,U锁等待TRAN2 S锁释放转换为X锁
在 TRAN2 中执行以下 SQL
UPDATE dbo.Brand SET BrandName='ZBrand' WHERE BrandId=2
Run Code Online (Sandbox Code Playgroud)
然后就会出现死锁。
上行死锁正如描述的那样,是用U锁来防止的。但僵局仍然发生。
所以我的问题是:U锁和X锁有什么不同?哪些情况下可以不用X锁来防止死锁呢?
该UPDATE操作分为两步:
(U)首先使用(更新)锁读取现有值
然后该锁被转换为独占(X)锁以写回新的(更新的)值。
由于您的REPEATABLE READ隔离级别,并且因为您这样安排语句,是的,您将陷入僵局。但我真的不明白这与锁有什么关系update......(这实际上只是因为您这样安排代码并且因为您正在使用REPEATABLE READ)。
锁的主要“好处”(U)是(S)此时其他共享锁仍然是可能的。例如,当一个事务读取要使用锁更新的值时,另一个事务可以使用a 中的共享锁(U)读取相同的值(如果您有独占锁,则这不起作用,例如当您执行 a 时)(S)SELECT(X)DELETE
如果您有两个事务都只单独执行UPDATE(不SELECT使用REPEATABLE READ) - 那么(U)第一个事务所采取的锁定将阻止第二个事务也读取该值(因为(U)锁不兼容 - 如果TRAN1在一行上有更新锁,TRAN2无法获取其更新锁)。这使得“读取现有值、更新它、写回它”成为原子操作,并防止两个事务同时在同一行上启动更新过程。
| 归档时间: |
|
| 查看次数: |
5952 次 |
| 最近记录: |