更新声明中的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不需要额外的锁定,因为事务已经获得对所讨论的行的独占访问权限。

链接地址: http://www.djcxy.com/p/5619.html

上一篇: DeadLock in Update Statement and Usage of UPDLOCK Hint

下一篇: Understanding effects of with (updlock, rowlock) on a query in SQL Server