更新声明中的DeadLock和UPDLOCK提示的用法
对于偶尔的以下事务,当此事务同时被调用相同的订单时,我收到死锁锁定错误。
BEGIN TRANSACTION
IF EXISTS (SELECT orderID FROM [Orders]WHERE orderID=@OrderId)
BEGIN
UPDATE [Orders] SET
[orderXml] =@orderXml
,[updatedDateTime] = @updatedDateTime
WHERE
[orderId] = @OrderId AND @updatedDateTime > updatedDateTime
END
if @@ROWCOUNT = 0
BEGIN
DELETE OrderLine
WHERE
orderID=@OrderId
END
COMMIT TRANSACTION
DeadLock图:
<resource-list>
<keylock hobtid="72057594039042048" dbid="13" objectname="OrderDB.dbo.Orders" indexname="PK_Order" id="lockac2e8d80" mode="U" associatedObjectId="72057594039042048">
<owner-list>
<owner id="process80736748" mode="U"/>
</owner-list>
<waiter-list>
<waiter id="process80739b88" mode="U" requestType="convert"/>
</waiter-list>
</keylock>
<keylock hobtid="72057594039042048" dbid="13" objectname=" OrderDB.dbo.Orders" indexname="PK_Order" id="lockac2e8d80" mode="U" associatedObjectId="72057594039042048">
<owner-list>
<owner id="process80739b88" mode="S"/>
</owner-list>
<waiter-list>
<waiter id="process80736748" mode="X" requestType="convert"/>
</waiter-list>
</keylock>
</resource-list>
PK_Order是订单表的OrderId(varchar)列的主键。 该表还在updatedDateTime(datetime2)列上获得了Non聚集索引。
问题:当我在上面的update语句中使用WITH(UPDLOCK)提示时,死锁似乎消失了。 建议使用UPDLOCK提示还是应该将事务隔离级别设置为可序列化。 在上面的delete语句中也可以使用UPDLOCK提示。
这是一个经典的死锁案例。 访问模式是可读写的。 两个trans读,然后都写不出来。
你采取“写入”锁( UPDLOCK
)的解决方案是好的。 使用UPDLOCK, ROWLOCK, HOLDLOCK
,我认为这是最好的例子。
SERIALIZABLE
没有帮助,因为该模式仍然是可读写的。
DELETE
不需要额外的锁定,因为事务已经获得对所讨论的行的独占访问权限。
上一篇: DeadLock in Update Statement and Usage of UPDLOCK Hint
下一篇: Understanding effects of with (updlock, rowlock) on a query in SQL Server