問題のSqlServer2008 R2インスタンスは、高負荷のOLTP本番サーバーです。デッドロックの問題は数日前に発生しましたが、まだ解決されていません。デッドロックに関連するストアドプロシージャとその他の詳細をリストしたXmlデッドロックレポートを受け取りました。最初に、このxmlから事実をリストアップしようとします。
デッドロックには、SP1とSP2の2つのストアドプロシージャが関係しています。レポートによると、SP1は分離レベル「Serializable」で実行され、SP2は「ReadCommitted」で実行されていました。
以下を調査しました。
SP内またはコードでSP1のIsolationLevelを「Serializable」に設定していますか?- いいえ。
IsolationLevelが「Serializable」である他のSPはSP1を呼び出していますか?- いいえ。
SP1で使用されるテーブルは、分離レベルが「シリアル化可能」である他のSPによって呼び出されますか?- はい。
分離レベルが「シリアル化可能」に設定され、SP1と同じテーブルにアクセスするSPがありますが、デッドロックレポートにはSP1とSP2しか表示されていないため、デッドロック時に実行されていたかどうかはわかりません。
考え方:
次の考えられる原因を検討しました。
SP1が「シリアル化可能」として実行されているため、デッドロックが発生しています。-設定していないのに、なぜこのSPがSerializableで実行されているのですか?分離レベルは(ロックのように)エスカレートしていますか?これを理解してReadCommittedとして実行すると、問題は解決しますか?
他のSPが実行されており、SP1が使用するテーブルがロックされ、SP1とSP2の間にデッドロックが発生します。-このSPはデッドロックレポートにリストされませんか?デッドロックレポートはそのような依存関係を見逃す可能性がありますか?はいの場合、部分的な情報しか取得していない可能性があります。ただし、これでもSP1がSerializableでどのように実行されているかは解決されません。
提案:
この情報が問題の解決に十分でない場合、自分の目的のためにSQL Serverからより多くの情報を取得するにはどうすればよいですか?また、どのような情報を収集する必要がありますか?
この問題を解決するために追求する他の考え方はありますか?
更新:
これは、デッドロックのトレースログ情報です。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つの異なるテーブル(Table1からTable5)からデータを取得する選択を実行しています(内部クエリなどを使用)。SP2はTable1の更新を実行します。
興味深いのは、SP2が更新する列の1つが、Table1の外部キーフィールドとTable2の主キーであり、Table1とTable2の両方がSP1のselectステートメントの一部であるということです。これが適切かどうかはわかりませんが、見逃したくありませんでした。なんでも。
注:indexname = "Index1"(上記のデッドロックグラフ内)-Index1は、Table1の外部キーおよびTable2の主キーと同じ列にあります。