2011-09-03 177 views
1

有人可以告訴我爲什麼下面的SQL Server查詢是死鎖和解決方案是什麼修復它?這是爲什麼SQL Server查詢死鎖?

<deadlock-list> 
    <deadlock victim="process88b5b8"> 
    <process-list> 
     <process id="process88b5b8" taskpriority="0" logused="76132" waitresource="RID: 32:1:151867:174" waittime="5093" ownerId="65554098" transactionguid="0xedf3314c05f1124cbe8d480cd092e03e" transactionname="DTCXact" lasttranstarted="2011-09-02T19:00:29.690" XDES="0x1029e040" lockMode="S" schedulerid="1" kpid="5108" status="suspended" spid="118" sbid="0" ecid="0" priority="0" transcount="2" lastbatchstarted="2011-09-02T19:00:31.317" lastbatchcompleted="2011-09-02T19:00:31.300" hostname="MELWFPL382S" hostpid="0" loginname="MM4" isolationlevel="repeatable read (3)" xactid="65554098" currentdb="32" lockTimeout="4294967295" clientoption1="671088672" clientoption2="128056"> 
     <executionStack> 
      <frame procname="adhoc" line="1" stmtstart="78" sqlhandle="0x020000004b4b0a0d63e1040095143cbaa0174ffc3e076067"> delete from PARTIES where [email protected] and ISCOUNTERPARTY='N' and PARTYID in (select PARTYID from NAB_PARTY_EXTEND (nolock) where [email protected])  </frame> 
      <frame procname="unknown" line="1" sqlhandle="0x000000000000000000000000000000000000000000000000">unknown  </frame> 
     </executionStack> 
     <inputbuf>(@P0 nvarchar(4000),@P1 nvarchar(4000))delete from PARTIES where [email protected] and ISCOUNTERPARTY='N' and PARTYID in (select PARTYID from NAB_PARTY_EXTEND (nolock) where [email protected])     </inputbuf> 
     </process> 
     <process id="process9196a8" taskpriority="0" logused="132612" waitresource="RID: 32:1:140302:31" waittime="5046" ownerId="65554657" transactionguid="0x7313c78fecc8914dac3ed821cd7c21fe" transactionname="DTCXact" lasttranstarted="2011-09-02T19:00:34.100" XDES="0x12835778" lockMode="S" schedulerid="2" kpid="3692" status="suspended" spid="94" sbid="0" ecid="0" priority="0" transcount="2" lastbatchstarted="2011-09-02T19:00:35.690" lastbatchcompleted="2011-09-02T19:00:35.687" hostname="MELWFPL382S" hostpid="0" loginname="MM4" isolationlevel="repeatable read (3)" xactid="65554657" currentdb="32" lockTimeout="4294967295" clientoption1="671088672" clientoption2="128056"> 
     <executionStack> 
      <frame procname="adhoc" line="1" stmtstart="78" sqlhandle="0x020000004b4b0a0d63e1040095143cbaa0174ffc3e076067">delete from PARTIES where [email protected] and ISCOUNTERPARTY='N' and PARTYID in (select PARTYID from NAB_PARTY_EXTEND (nolock) where [email protected])  </frame> 
      <frame procname="unknown" line="1" sqlhandle="0x000000000000000000000000000000000000000000000000">unknown  </frame> 
     </executionStack> 
     <inputbuf>(@P0 nvarchar(4000),@P1 nvarchar(4000))delete from PARTIES where [email protected] and ISCOUNTERPARTY='N' and PARTYID in (select PARTYID from NAB_PARTY_EXTEND (nolock) where [email protected])     </inputbuf> 
     </process> 
    </process-list> 
    <resource-list> 
     <ridlock fileid="1" pageid="140302" dbid="32" objectname="mm4_melwfpl382s.dbo.COUNTERPARTYSSI" id="lock170fa500" mode="X" associatedObjectId="72057595803336704"> 
     <owner-list> 
      <owner id="process88b5b8" mode="X" /> 
     </owner-list> 
     <waiter-list> 
      <waiter id="process9196a8" mode="S" requestType="wait" /> 
     </waiter-list> 
     </ridlock> 
     <ridlock fileid="1" pageid="151867" dbid="32" objectname="mm4_melwfpl382s.dbo.COUNTERPARTYSSI" id="lock20e65d80" mode="X" associatedObjectId="72057595803336704"> 
     <owner-list> 
      <owner id="process9196a8" mode="X" /> 
     </owner-list> 
     <waiter-list> 
      <waiter id="process88b5b8" mode="S" requestType="wait" /> 
     </waiter-list> 
     </ridlock> 
    </resource-list> 
    </deadlock> 
</deadlock-list> 

我不明白的是兩個進程如何在同一個對象上有獨佔鎖。

PARTIES表上有一個索引(IDX_NC_PARTIES_PARTYEXTERNALREF_ISCOUNTERPARTY_PARTYID),數據庫設置爲讀取已提交的快照。

謝謝,

韋恩。

+0

也許您擁有的觸發器正在激活並鎖定資源。如果你有觸發器,首先嚐試禁用它們,看看你的查詢是否運行。 – itsols

+0

您的刪除查詢有問題嗎? – itsols

+0

如果涉及觸發器,我會在星期一檢查。不幸的是,這不是那種容易重現的問題,即我需要將數千條消息輸入到我們的應用程序中,並在發生死鎖之前等待數小時。死鎖是隨機發生的,即它看起來像是各種過程之間的時間問題。添加上述索引是我最近嘗試擺脫僵局。 – Wayne

回答

8
  • 過程9196a8具有151867頁槽174在X模式,並希望頁140302槽31在S模式
  • 過程88b5b8具有140302頁槽31在X模式,並希望151867頁槽174在S模式
  • 這兩個刪除運行在isolationlevel="repeatable read (3)"

所以死鎖發生在表的基堆上(RID鎖而不是鍵鎖意味着堆不是Btree)。高隔離級別(可能由DTC引起,由xact名稱判斷)使得RCSI設置無關緊要。

什麼類型的列是PARTYEXTERNALREF和PARTYTYPE?傳入的參數是NVARCHAR(即Unicode),如果這些列是VARCHAR(即Ascii),那麼由於data type precedence的規則,將不會使用NC索引。由於涉及的表掃描以及使用中的高隔離級別,死鎖幾乎是不可避免的。

解決方法是使用@ P0和@ P1的VARCHAR類型參數,以便利用NC索引來避免表掃描。

如果參數已經VARCHAR類型的,你可以從一個NC上尋求執行計劃確認被使用時,我的第一個問題將是其他在事務做什麼,不是delete語句其他?

順便說一句,你只給出NC指數的名稱,但我認爲是在(PARTYEXTERNALREF, ISCOUNTERPARTY, PARTYID)

更新

由於您的評論說,列 NVARCHAR那麼表掃描的假設也許是錯誤的。有三個可能導致需要調查死鎖:

  • 任何其他語句由交易前的刪除(這是最有可能的)
  • 在行兩個DELETE語句選擇任何重疊參與運行在僵局
  • hash collision

對於前兩種假設只有你現在就可以做任何事情(調查,如果他們是正確的)。對於最後一個,我可以告訴你如何驗證它,但不是微不足道的。這不太可能發生,也難以證明,但這是可能的。既然你知道死鎖情況(附XML)的,使用它作爲研究基地:

  • 使用DBCC PAGE (<restored db id>, 1, 151867, 3)檢查值恢復點即時數據庫with stop at 2011-09-02T19:00:29.690
  • 運行DBCC TRACEON(3604,-1)
  • 副本在使用DBCC PAGE槽174
  • (i,1,140302,3)`在槽31
  • 運行SELECT %%lockres%% FROM PARTIES WHERE PARTYEXTERNALREF = ... AND ISCOUNTERPARTY='N' and PARTYID=...檢查值,並通過在上述
  • compars所述讀取的值導致鎖哈希值,如果他們匹配,那麼你有一個哈希碰撞,這導致了死鎖。
+0

前兩列是nvarchar,第三列是int。你在最後的假設中是正確的。順便說一下,我不是DBA,所以我需要更多時間來消化上述信息。從我看到的只有一個刪除和一個select語句涉及。 – Wayne