我正在阅读Understanding Locking in 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
现在,TRAN1为RID授予S锁
在TRAN2中执行以下SQL
BEGIN TRAN
SELECT BrandName FROM dbo.Brand WHERE BrandId=2
现在,TRAN2为与TRAN1
相同的RID资源授予S锁在TRAN1中执行以下SQL
UPDATE dbo.Brand SET BrandName='YBrand' WHERE BrandId=2
现在,TRAN1 S锁定转换为U锁定并且U锁定等待TRAN2 S锁定释放转换为X锁定
在TRAN2中执行以下SQL
UPDATE dbo.Brand SET BrandName='ZBrand' WHERE BrandId=2
然后发生死锁。
向上死锁与U锁用于防止的描述完全相同。但死锁仍然存在。
所以我的问题是:U锁与X锁不同?哪种情况可以防止死锁而不是使用X锁?
答案 0 :(得分:2)
UPDATE
操作分为两步:
首先使用(U)
(更新)锁读取现有值
然后将该锁转换为独占(X)
锁以写回新的(更新的)值。
由于您的REPEATABLE READ
隔离级别,并且因为您已经安排了这样的陈述,是的,您将陷入僵局。但我真的不明白这与update
锁定有什么关系......(这真的只是因为你已经安排好这样的代码而且因为你'重新使用REPEATABLE READ
)。
主要"福利" (U)
锁的问题是,在那段时间内仍然可以使用其他(S)
共享锁。例如。当一个事务使用(U)
锁读取要更新的值时,另一个事务可以使用(S)
中的SELECT
共享锁读取相同的值(如果{您有一个独有的(X)
锁定,例如当您执行DELETE
)
如果您有两个仅仅UPDATE
仅SELECT
与REPEATABLE READ
进行交易的交易 - 那么第一笔交易所采取的(U)
锁将阻止第二个事务也来自读取该值(因为(U)
锁定不兼容 - 如果TRAN1
行上有更新锁定,TRAN2
无法获得更新锁定)。这使得"读取现有值,更新它,将其写回"原子操作,并防止两个事务同时在同一行上启动更新过程。
答案 1 :(得分:0)
更新(U)锁会自动放在UPDATE语句上的DB中的数据上。 主要任务是保护数据库中的数据不被多个事务同时更改,并避免死锁。
Update语句由3部分组成:读取数据,计算新值,写入数据。我们无法为阅读部分应用排他(X)锁。因此,Update锁并不是真正的独立锁,而是SHARED和EXCLUSIVE锁的混合。
假定两个进程都使用不同的访问路径来搜索要修改的同一资源(例如,Customers表中的同一客户行),并且它们都可以同时到达所需的资源。如果他们俩都在他们正在检查的数据上获得SHARED锁,那么他们都可以锁定要更改的资源,但是在进行修改之前,他们必须将其锁转换为EXCLUSIVE锁。由于其他进程将具有SHARED锁定,因此无法授予EXCLUSIVE锁定。每个进程都将具有SHARED锁,并且每个进程都将尝试将其更改为EXCLUSIVE锁,但是由于另一个进程的存在,两个进程均无法继续进行。这是一种僵局,称为“转换僵局”。
如果SQL Server使用UPDATE锁,则不会发生死锁。
UPDATE锁与SHARED锁兼容,但与EXCLUSIVE锁或其他UPDATE锁不兼容。因此,如果两个进程正在搜索相同的数据资源,则第一个到达该进程的资源将获得一个UPDATE锁,然后第二个进程将无法获得任何锁,而将等待第一个进程完成。由于第一个进程没有被阻止,因此它可以将其UPDATE锁定转换为EXCLUSIVE锁定,进行数据修改,并完成其事务并释放其锁定。然后第二个过程可以进行更改。
共享(S)锁-在需要读取对象时发生。
排他(X)锁-发生是为了防止其他事务修改或访问锁定的对象。