7

問題中的Sql Server 2008 R2實例是一個重負載的OLTP生產服務器。這個僵局問題幾天前就出現了,但仍然沒有解決。我們收到了列出涉及死鎖的存儲過程和其他一些細節的Xml死鎖報告。我會嘗試從這個xml中首先列出事實:SQL Server 2008 R2中的死鎖問題(.Net 2.0應用程序)

兩個存儲過程涉及死鎖,比如SP1和SP2。根據報告SP1運行在隔離級別「Serializable」SP2運行在「ReadCommitted」

我們已經調查了以下內容:

  • 我們是否 「序列化」 內部SP或 碼設置SP1 的的IsolationLevel? - 否

  • 其他SP的IsolationLevel 是「Serializable」調用SP1嗎? - 否

  • SP1使用的表由SP1調用 其他任何具有隔離的SP 級別爲「可序列化」? - 是的。 。它有隔離 級別設置爲「序列化」和 訪問相同的表SP1, 的SP,但我們不知道他們是否 是在 僵局的時間或不作死鎖
    報告僅運行展示了SP1和SP2。思想

線:
我們曾考慮以下可能的原因:

  • 死鎖發生,因爲SP1是 運行的 「序列化」。 - 爲什麼 這個SP運行在Serializable中時 我還沒有設置?隔離 級別是否正在升級(就像鎖一樣)?如果 我們計算出來,並使其運行爲 ReadCommitted,將問題解決爲 ?

  • 任何其他SP正在運行,鎖定SP1使用的 表,並導致SP1和SP2之間出現 死鎖。 - 是否將此SP列入 死鎖報告中?報告 報告可能錯過這樣的依賴關係嗎?如果是的話 那麼我們可能只會得到部分 的信息。但是,這仍然不能解決SP1在 可序列化中運行的方式。

建議:

  • 如果這個信息是不是在解決問題的足夠 ,我怎麼能 從SQL 服務器獲得更多的信息,我的目的,什麼 信息應該我嘗試收集?

  • 任何其他思路你會在解決這個問題時追求 ?

更新:
這是僵局跟蹤日誌信息。我已經更改了SP的名稱等,但已經檢查並確認這些更改不會錯過任何相關信息。檢查筆記後續的代碼對錶等

?<EVENT_INSTANCE> 
    <EventType>DEADLOCK_GRAPH</EventType> 
    <PostTime>2010-09-07T11:27:47.870</PostTime> 
    <SPID>16</SPID> 
    <TextData> 
    <deadlock-list> 
     <deadlock victim="process5827708"> 
     <process-list> 
      <process id="process5827708" taskpriority="0" logused="0" waitresource="KEY: 7:72057594228441088 (8d008a861f4f)" 
        waittime="5190" ownerId="1661518243" transactionname="SELECT" lasttranstarted="2010-09-07T11:27:42.657" 
        XDES="0x80bf3b50" lockMode="RangeS-S" schedulerid="4" kpid="2228" status="suspended" spid="76" sbid="0" 
        ecid="0" priority="0" trancount="0" lastbatchstarted="2010-09-07T11:27:42.657" 
        lastbatchcompleted="2010-09-07T11:27:42.657" clientapp=".Net SqlClient Data Provider" 
        hostname="xxx" hostpid="5988" loginname="xxx" isolationlevel="serializable (4)" 
        xactid="1661518243" currentdb="7" lockTimeout="4294967295" clientoption1="673185824" clientoption2="128056"> 
      <executionStack> 
       <frame procname="SP1" line="12" stmtstart="450" stmtend="6536" 
        sqlhandle="0x0300070090cbdc7742720c00e99d00000100000000000000"> 
       Select ... from Table1, Table2, Table4, Table5 
       </frame> 
      </executionStack> 
      <inputbuf> 
       Proc [Database Id = 7 Object Id = 2010958736] 
      </inputbuf> 
      </process> 
      <process id="process5844bc8" taskpriority="0" logused="1873648" waitresource="KEY: 7:72057594228441088 (0e00ce038ed0)" 
        waittime="4514" ownerId="1661509575" transactionname="user_transaction" lasttranstarted="2010-09-07T11:27:40.423" 
        XDES="0x37979ae90" lockMode="X" schedulerid="7" kpid="3260" status="suspended" spid="104" sbid="0" ecid="0" 
        priority="0" trancount="2" lastbatchstarted="2010-09-07T11:27:43.350" lastbatchcompleted="2010-09-07T11:27:43.350" 
        clientapp=".Net SqlClient Data Provider" hostname="xxx" hostpid="5988" loginname="xxx" 
        isolationlevel="read committed (2)" xactid="1661509575" currentdb="7" lockTimeout="4294967295" 
        clientoption1="673185824" clientoption2="128056"> 
      <executionStack> 
       <frame procname="SP2" line="68" stmtstart="5272" stmtend="5598" 
        sqlhandle="0x030007003432350f109a0c00e99d00000100000000000000"> 
       UPDATE Table1 ... 
       </frame> 
      </executionStack> 
      <inputbuf> 
       Proc [Database Id = 7 Object Id = 255144500] 
      </inputbuf> 
      </process> 
     </process-list> 
     <resource-list> 
      <keylock hobtid="72057594228441088" dbid="7" objectname="Table1" indexname="Index1" 
        id="lock448e2c580" mode="X" associatedObjectId="72057594228441088"> 
      <owner-list> 
       <owner id="process5844bc8" mode="X" /> 
      </owner-list> 
      <waiter-list> 
       <waiter id="process5827708" mode="RangeS-S" requestType="wait" /> 
      </waiter-list> 
      </keylock> 
      <keylock hobtid="72057594228441088" dbid="7" objectname="Table1" indexname="Index1" 
        id="lock2ba335880" mode="RangeS-S" associatedObjectId="72057594228441088"> 
      <owner-list> 
       <owner id="process5827708" mode="RangeS-S" /> 
      </owner-list> 
      <waiter-list> 
       <waiter id="process5844bc8" mode="X" requestType="wait" /> 
      </waiter-list> 
      </keylock> 
     </resource-list> 
     </deadlock> 
    </deadlock-list> 
    </TextData> 
    <TransactionID /> 
    <LoginName>xx</LoginName> 
    <StartTime>2010-09-07T11:27:47.867</StartTime> 
    <ServerName>xxx</ServerName> 
    <LoginSid>xxx</LoginSid> 
    <EventSequence>116538375</EventSequence> 
    <IsSystem>1</IsSystem> 
    <SessionLoginName /> 
</EVENT_INSTANCE> 

SP1正在執行一個選擇,從5個不同的表(表1至表5)中獲取數據的詳細信息(使用內部查詢等)SP2執行對錶1的更新。
有趣的是,SP2更新的一列是Table1中的外鍵字段和Table2的主鍵,而Table1和Table2都是SP1的select語句的一部分,不確定這是否相關,但不希望錯過任何東西。

注意:indexname =「Index1」(在上面的死鎖圖中) - Index1與Table1中的外鍵和Table2的主鍵位於同一列。

+0

作爲開始,您需要提供'DBCC TRACEON(1222,-1)'的輸出和死鎖中涉及的模式的位 – 2010-09-16 10:56:10

+0

我有1222蹤跡,但如何使其可用。是否有可能上傳一個文件的問題,或者我應該只是把它與問題(真的很大)? – 2010-09-16 12:18:45

+0

只需抓住幾個僵局鏈並嵌入答案。然後爲事務和相關模式提供SQL – 2010-09-16 14:07:19

回答

2

檢查此MSDN article其中指出:

隔離級別具有連接全範圍,並且一旦設置了一個 與SET TRANSACTI的連接在隔離級別語句中,其 保持有效,直到連接關閉或設置了另一個隔離級別 。當連接關閉並返回池時,將保留來自上一個SET TRANSACTION ISOLATION LEVEL 語句的隔離級別 。後續連接重用連接使用連接池 時有效的隔離級別。

問題是連接打開時出現了Serializable隔離級別;關聯的事務被處置,連接也被處置,但連接沒有被銷燬並且進入連接池。下一次發出連接請求時(使用相同的連接字符串),這個連接會返回並且由於查詢沒有指定任何隔離級別,所以它在Serializable隔離級別中執行。

基本上,如果你有一個連接池並在特定的隔離級別打開一個連接,比方說Serializable,那麼連接將返回到隔離級別設置爲Serializable的池。下一次請求連接時,您不能確定此連接將不會返回,因此即使默認隔離級別爲ReadCommitted,您也可能會獲得其中一個「可序列化」連接。

另一個需要注意的是,每次將隔離級別設置爲Serializable(或其他任何事情)時,您可能會選擇不同的連接,並且可能會通過將連接池中的更多連接設置爲隔離級別可序列化(或任何你設定的)。

我沒有找到任何機制來重置處置連接(當它執行我的查詢後返回到連接池)。一種解決方法是顯式重置每個連接的隔離級別。但這很乏味。

所以最好的選擇是爲不同的隔離級別創建單獨的連接池

1

在sp1中的那些選定表格之後添加(nolock),以確保無法將讀鎖定添加到這些特定表格。