更新语句中的DeadLock和UPDLOCK提示的用法

时间:2014-04-22 19:55:50

标签: sql-server transactions deadlock

对于以下事务,我偶尔会在同一个订单同时调用此事务时收到Dead Lock错误。

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 Graph:

<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是Orders Table的OrderId(varchar)列的主键。该表还在updatedDateTime(datetime2)列上有一个非聚集索引。

问题:当我在上面的更新语句中使用WITH(UPDLOCK)提示时,死锁似乎消失了。 是否建议使用UPDLOCK提示或我应该将事务隔离级别设置为Serializable。 也建议在上面的delete语句中使用UPDLOCK提示。

1 个答案:

答案 0 :(得分:1)

这是一个典型的死锁案例。访问模式是read-then-write。两个trans都读,然后都写不出来。

你采取“写”锁(UPDLOCK)的解决方案是好的。使用我认为最适合此类案例的UPDLOCK, ROWLOCK, HOLDLOCK

SERIALIZABLE没有帮助,因为该模式仍然是read-then-write。

DELETE不需要额外的锁定,因为该事务已获得对相关行的独占访问权。