2个SQL表上的全或无独占锁

时间:2012-06-29 16:52:33

标签: sql sql-server locking deadlock

我的简单测试表明我可以获得2个表的独占锁定或推迟获取锁定,直到可以使用这样的查询立即获取两个:

SELECT AutoKey, OnHand FROM ONNM(XLOCK) CROSS JOIN OITM(XLOCK)
WHERE ObjectCode IN ('20', '10000048') AND ItemCode = @ItemCode

CROSS JOIN的关键特性曾用于在单个查询中包含多个表。我确认如果在另一个事务中@ItemCode的OITM行上已存在独占锁,则该语句在ONNM上不会引入任何锁,直到它可以获取两个锁。但是,在更复杂的完整测试运行中,SQL事件探查器会返回一些冲突的信息。我已将SQL事件探查器结果导入表中并执行以下查询:

select rownum, e.name, EventClass, TextData, SPID, ClientProcessID from #pmit t
join sys.trace_events e on t.EventClass = e.trace_event_id
where rownum between 275799 and 546130
and (TextData LIKE '(ca73a6396124)' or TextData LIKE '(36fa3e654c8f)'
     or TextData LIKE '%(XLOCK)%' or TextData LIKE '%DeadLock%')
order by rownum

这些是我回来的结果:

Row    | Event                | SPID | Text
275799 | SP:StmtStarting      | 99   | SELECT AutoKey, OnHand FROM ONNM(XLOCK) CROSS JOIN OITM(XLOCK) WHERE ObjectCode IN ('20', '10000048') AND ItemCode = @ItemCode
304781 | Lock:Acquired        | 139  | (36fa3e654c8f)
305365 | Lock:Acquired        | 139  | (36fa3e654c8f)
351093 | Lock:Acquired        | 139  | (ca73a6396124)
468768 | Lock:Released        | 13   | (ca73a6396124)
470912 | Lock:Released        | 13   | (36fa3e654c8f)
470922 | Lock:Acquired        | 164  | (36fa3e654c8f)
470928 | Lock:Released        | 164  | (36fa3e654c8f)
470971 | Lock:Acquired        | 99   | (36fa3e654c8f)
471013 | RPC:Completed        | 99   | exec sp_executesql N'SELECT AutoKey, OnHand FROM ONNM(XLOCK) CROSS JOIN OITM(XLOCK) WHERE ObjectCode IN (''20'', ''10000048'') AND ItemCode = @ItemCode',N'@ItemCode nvarchar(3)',@ItemCode=N'FX1'
490843 | SP:StmtStarting      | 78   | SELECT AutoKey, OnHand FROM ONNM(XLOCK) CROSS JOIN OITM(XLOCK) WHERE ObjectCode IN ('20', '10000048') AND ItemCode = @ItemCode
490848 | Lock:Acquired        | 78   | (ca73a6396124)
495391 | Lock:Acquired        | 114  | (36fa3e654c8f)
495396 | Lock:Acquired        | 114  | (36fa3e654c8f)
542738 | Lock:Deadlock Chain  | 6    | Deadlock Chain SPID = 78 (36fa3e654c8f)                                                                                                                                                                                                                                                  
545746 | Lock:Deadlock Chain  | 6    | Deadlock Chain SPID = 154 (36fa3e654c8f)                                                                                                                                                                                                                                                  
545769 | Lock:Deadlock Chain  | 6    | Deadlock Chain SPID = 114 (ca73a6396124)                                                                                                                                                                                                                                                  
545982 | Lock:Deadlock        | 78   | (36fa3e654c8f)
545985 | RPC:Completed        | 78   | exec sp_executesql N'SELECT AutoKey, OnHand FROM ONNM(XLOCK) CROSS JOIN OITM(XLOCK) WHERE ObjectCode IN (''20'', ''10000048'') AND ItemCode = @ItemCode',N'@ItemCode nvarchar(3)',@ItemCode=N'FC3'
545990 | Lock:Released        | 78   | (ca73a6396124)
545998 | Lock:Acquired        | 114  | (ca73a6396124)
546130 | Deadlock graph       | 17   | (See below)

死锁图如下:

<deadlock-list>
   <deadlock victim="process5e3ae08">
      <process-list>
         <process id="process5e3ae08" taskpriority="0" logused="0" waitresource="KEY: 6:72057598620205056 (36fa3e654c8f)" waittime="9507" ownerId="513854688" transactionname="user_transaction" lasttranstarted="2012-06-28T13:38:54.463" XDES="0x1bbf9b950" lockMode="RangeX-X" schedulerid="6" kpid="13248" status="suspended" spid="78" sbid="0" ecid="0" priority="0" trancount="1" lastbatchstarted="2012-06-28T13:38:54.483" lastbatchcompleted="2012-06-28T13:38:54.463" clientapp=".Net SqlClient Data Provider" hostname="PMIUSRSTL00013" hostpid="3180" loginname="RICFSE01SAPB1" isolationlevel="serializable (4)" xactid="513854688" currentdb="6" lockTimeout="4294967295" clientoption1="671088672" clientoption2="128056">
            <executionStack>
               <frame procname="adhoc" line="1" stmtstart="46" sqlhandle="0x02000000151c651e3c8b4437ee414cefdbc46b70aceca960">  SELECT AutoKey, OnHand FROM ONNM(XLOCK) CROSS JOIN OITM(XLOCK) WHERE ObjectCode IN (&apos;20&apos;, &apos;10000048&apos;) AND ItemCode = @ItemCode     </frame>
               <frame procname="unknown" line="1" sqlhandle="0x000000000000000000000000000000000000000000000000">  unknown     </frame>
            </executionStack>
            <inputbuf>  (@ItemCode nvarchar(3))SELECT AutoKey, OnHand FROM ONNM(XLOCK) CROSS JOIN OITM(XLOCK) WHERE ObjectCode IN (&apos;20&apos;, &apos;10000048&apos;) AND ItemCode = @ItemCode    </inputbuf>
         </process>
         <process id="process5e45048" taskpriority="0" logused="0" waitresource="KEY: 6:72057598620205056 (36fa3e654c8f)" waittime="12866" ownerId="513845303" transactionname="SELECT" lasttranstarted="2012-06-28T13:38:28.463" XDES="0x80048e50" lockMode="S" schedulerid="7" kpid="12772" status="suspended" spid="154" sbid="0" ecid="0" priority="0" trancount="0" lastbatchstarted="2012-06-28T13:38:28.390" lastbatchcompleted="2012-06-28T13:38:28.380" lastattention="2012-06-28T13:38:27.927" clientapp="TagClerkService" hostname="PMIUSRSTW00008" hostpid="2772" loginname="RICFSE01SAPB1" isolationlevel="read committed (2)" xactid="513845303" currentdb="6" lockTimeout="4294967295" clientoption1="671088672" clientoption2="128056">
            <executionStack>
               <frame procname="adhoc" line="1" sqlhandle="0x020000000d86e30171762b464b35e0923de532c497188b81">  SELECT T0.*  FROM [dbo].[ONNM] T0     </frame>
            </executionStack>
            <inputbuf>  SELECT T0.*  FROM [dbo].[ONNM] T0    </inputbuf>
         </process>
         <process id="process5e31708" taskpriority="0" logused="25240" waitresource="KEY: 6:72057597517103104 (ca73a6396124)" waittime="2031" ownerId="513831818" transactionguid="0xdefde99023405d4a96d101faac79ef96" transactionname="user_transaction" lasttranstarted="2012-06-28T13:38:19.237" XDES="0xd68df950" lockMode="RangeS-S" schedulerid="5" kpid="11564" status="suspended" spid="114" sbid="0" ecid="0" priority="0" trancount="1" lastbatchstarted="2012-06-28T13:38:58.560" lastbatchcompleted="2012-06-28T13:38:58.490" lastattention="2012-06-28T12:48:33.060" clientapp="TagClerkService" hostname="PMIUSRSTL00011" hostpid="2908" loginname="RICFSE01SAPB1" isolationlevel="serializable (4)" xactid="513831818" currentdb="6" lockTimeout="4294967295" clientoption1="671088672" clientoption2="128056">
            <executionStack>
               <frame procname="adhoc" line="1" stmtstart="24" sqlhandle="0x02000000a329a30eb1319f2df684296f889a1613a585b3a0">  SELECT ISNULL(a.U_FSE_ApplicationUsr,a.UserSign) ,a.DocNum ,b.LineNum ,f.IsLotTraced ,h.LotNumber ,b.WhsCode ,n.Bin ,g.Quantity ,b.LineTotal ,i.OnTimeDeliveryDaysEarly ,i.OnTimeDeliveryDaysLate ,i.ReceiptVarianceUnderAllowed ,i.ReceiptVarianceOverAllowed ,k.ItemCode ,d.Revision ,a.Comments ,e.RolledMaterialCost ,e.RolledLaborCost ,e.RolledVariableOverheadCost ,e.RolledFixedOverheadCost ,e.RolledOutsideCost ,ISNULL(c.Quantity, c2.Quantity) ,c.DocumentLineDetailKey /* TODO: Handle serial numbers for blanket deliveries */ ,ISNULL(c.InventoryCode, c2.InventoryCode) ,k.InvntryUom ,r.Resource ,p.ItemName ,CASE WHEN m.MOKey IS NULL THEN NULL ELSE b.U_FSE_STypeItemQty END ,a.DocDate FROM OPDN a LEFT JOIN PDN1 b ON a.DocEntry=b.DocEntry  LEFT JOIN FSE_PurchaseGoodsReceiptLineDetail c ON (b.DocEntry=c.DocumentKey and b.LineNum=c.DocumentLineKey) LEFT JOIN FSE_PurchaseGoodsReceiptDeliveryLineDetail c2 ON (b.DocEntry=c2.DocumentKey and b.LineNum=c2.DocumentLineKey) LEFT JOIN FSE_MO m ON m.DocumentNumber = b.U_FSE_MONumbe     </frame>
               <frame procname="unknown" sqlhandle="0x000000000000000000000000000000000000000000000000">  unknown     </frame>
               <frame procname="FSDB00.dbo.SBO_SP_TransactionNotification" line="25" stmtstart="1588" stmtend="2032" sqlhandle="0x030006000a73d75dfe95d60059a000000100000000000000">  exec usp_FSE_HandleSBONotification @object_type, @transaction_type, @num_of_cols_in_key, @list_of_key_cols_tab_del, @list_of_cols_val_tab_del, @error out, @error_message out  -- keep this on one line    --PMI DataTransfer     </frame>
               <frame procname="adhoc" line="1" sqlhandle="0x01000600fd116804e00371a5000000000000000000000000">  EXECUTE SBO_SP_TransactionNotification N&apos;20&apos;,N&apos;A&apos;,1,N&apos;DocEntry&apos;,N&apos;134138&apos;     </frame>
            </executionStack>
            <inputbuf>  EXECUTE SBO_SP_TransactionNotification N&apos;20&apos;,N&apos;A&apos;,1,N&apos;DocEntry&apos;,N&apos;134138&apos;    </inputbuf>
         </process>
      </process-list>
      <resource-list>
         <keylock hobtid="72057598620205056" dbid="6" objectname="FSDB00.dbo.ONNM" indexname="ONNM_PRIMARY" id="lock1aa7d9880" mode="RangeX-X" associatedObjectId="72057598620205056">
            <owner-list/>
            <waiter-list>
               <waiter id="process5e3ae08" mode="RangeX-X" requestType="wait"/>
            </waiter-list>
         </keylock>
         <keylock hobtid="72057598620205056" dbid="6" objectname="FSDB00.dbo.ONNM" indexname="ONNM_PRIMARY" id="lock1aa7d9880" mode="RangeX-X" associatedObjectId="72057598620205056">
            <owner-list>
               <owner id="process5e31708" mode="RangeX-X"/>
            </owner-list>
            <waiter-list>
               <waiter id="process5e45048" mode="S" requestType="wait"/>
            </waiter-list>
         </keylock>
         <keylock hobtid="72057597517103104" dbid="6" objectname="FSDB00.dbo.OITM" indexname="OITM_PRIMARY" id="lock215ce6980" mode="X" associatedObjectId="72057597517103104">
            <owner-list>
               <owner id="process5e3ae08" mode="X"/>
            </owner-list>
            <waiter-list>
               <waiter id="process5e31708" mode="RangeS-S" requestType="wait"/>
            </waiter-list>
         </keylock>
      </resource-list>
   </deadlock>
</deadlock-list>

我的问题是,为什么SPID 78获得OITM上的锁定(ca73a6396124)(如果我没记错的话恰好代表ItemCode FC1)可能(正常),即使它无法获取ONNM上的锁定(36fa3e654c8f)。我的假设是SQL语句获得全有或全无锁?如果ONNM锁的持有者是在另一个进程中包含多个连接的事务中的另一个连接上的共享锁,它是否不成立? (我认为SPID 99是与SPID 114在同一过程中的另一个连接。)

这似乎是一个非常复杂的解密问题;我不知道是否有更好的方法可以避免死锁或找出发生的事情。

0 个答案:

没有答案