2017-02-14 11 views
3

特定の種類のデッドロックがどのように発生するのかを理解しようとしています。特定の種類のデッドロックの理解

私は2つのリソースと2つのプロセスを持つ非常に単純なデッドロックグラフを持っています。 1つはSELECT、もう1つはUPDATEです。私は、デッドロックを招く状況があることを理解していますが、この特定のシナリオではどうなるのか分かりません。

被害者のクエリ:

SELECT id_particle, id_event, dt_created, dt_rcvd, tlx_no, from_routename, re, deleted 
FROM msg_list 
WHERE to_routename = @P0 
AND ((dt_answ IS NULL AND b_complete = 0 AND id_event=6) OR (id_event = 10 AND deleted = 0) 
OR (from_id_post = 9705 AND deleted = 0)) 
ORDER BY dt_created ASC 

ウィナーズクエリ:

UPDATE msg_list 
SET 
    ID_EVENT=7, 
    STATUS='Answered', 
    DT_ANSW={ts '2017-02-12 05:34:14' 
WHERE ID_PARTICLE = 46211816 

完全なデッドロックグラフ:

<deadlock-list> 
<deadlock victim="process30aa42d468"> 
    <process-list> 
    <process id="process30aa42d468" taskpriority="0" logused="0" waitresource="PAGE: 6:1:155679 " waittime="921" ownerId="427175775" transactionname="SELECT" lasttranstarted="2017-02-12T05:34:48.293" XDES="0x3126fbba40" lockMode="S" schedulerid="4" kpid="10648" status="suspended" spid="184" sbid="0" ecid="0" priority="0" trancount="0" lastbatchstarted="2017-02-12T05:34:48.293" lastbatchcompleted="2017-02-12T05:34:48.280" lastattention="1900-01-01T00:00:00.280" clientapp="jTDS" hostname="LNS" hostpid="123" loginname="MsgStore" isolationlevel="read committed (2)" xactid="427175775" currentdb="6" lockTimeout="4294967295" clientoption1="671088672" clientoption2="128056"> 
    <executionStack> 
    <frame procname="tempdb.dbo.#jtds000003_____________________________________________________________________________________________________________0042FD9D" line="1" stmtstart="92" stmtend="668" sqlhandle="0x030002005819e1b4efce580018a7000001000000000000000000000000000000000000000000000000000000"> 
SELECT id_particle, id_event, dt_created, dt_rcvd, tlx_no, from_routename, re, deleted FROM msg_list WHERE to_routename = @P0 AND ((dt_answ IS NULL AND b_complete = 0 AND id_event=6) OR (id_event = 10 AND deleted = 0) OR (from_id_post = 9705 AND deleted = 0)) ORDER BY dt_created AS  </frame> 
    </executionStack> 
    <inputbuf> 
Proc [Database Id = 2 Object Id = -1260316328] </inputbuf> 
    </process> 
    <process id="process319282aca8" taskpriority="0" logused="21256" waitresource="PAGE: 6:1:396658 " waittime="869" ownerId="427175573" transactionname="implicit_transaction" lasttranstarted="2017-02-12T05:34:48.210" XDES="0x30c2dbc408" lockMode="IX" schedulerid="4" kpid="11980" status="suspended" spid="99" sbid="0" ecid="0" priority="0" trancount="2" lastbatchstarted="2017-02-12T05:34:48.430" lastbatchcompleted="2017-02-12T05:34:48.427" lastattention="2017-02-12T03:34:28.130" clientapp="NotesMover" hostname="LNS" hostpid="8828" loginname="Notesmover" isolationlevel="read committed (2)" xactid="427175573" currentdb="6" lockTimeout="4294967295" clientoption1="671088672" clientoption2="128058"> 
    <executionStack> 
    <frame procname="adhoc" line="1" stmtstart="364" stmtend="812" sqlhandle="0x020000006d523b316d15563a50b97ce8d56da3cf6d8fc4450000000000000000000000000000000000000000"> 
unknown  </frame> 
    <frame procname="adhoc" line="1" stmtend="554" sqlhandle="0x02000000d8b78713c51b1588947edf24f2d7b69031f4f1d60000000000000000000000000000000000000000"> 
unknown  </frame> 
    <frame procname="unknown" line="1" sqlhandle="0x0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000"> 
unknown  </frame> 
    </executionStack> 
    <inputbuf> 
UPDATE msg_list SET ID_EVENT=7, STATUS='Answered', DT_ANSW={ts '2017-02-12 05:34:14'WHERE ID_PARTICLE = 46211816  
    </inputbuf> 
    </process> 
    </process-list> 
    <resource-list> 
    <pagelock fileid="1" pageid="155679" dbid="6" subresource="FULL" objectname="MsgStore.dbo.msg_list" id="lock31683f2400" mode="IX" associatedObjectId="72057594523811840"> 
    <owner-list> 
    <owner id="process319282aca8" mode="IX"/> 
    </owner-list> 
    <waiter-list> 
    <waiter id="process30aa42d468" mode="S" requestType="wait"/> 
    </waiter-list> 
    </pagelock> 
    <pagelock fileid="1" pageid="396658" dbid="6" subresource="FULL" objectname="MsgStore.dbo.msg_list" id="lock2f80c2e300" mode="S" associatedObjectId="72057594523811840"> 
    <owner-list> 
    <owner id="process30aa42d468" mode="S"/> 
    </owner-list> 
    <waiter-list> 
    <waiter id="process319282aca8" mode="IX" requestType="wait"/> 
    </waiter-list> 
    </pagelock> 
    </resource-list> 
</deadlock> 
</deadlock-list> 

そして同じのグラフィカルな表現:

被害者:

Execution Plan Victim

Deadlock Graph

そしてここでは、これらの2つのクエリを実行するときに生成されたクエリプランがあります

受賞者:

Execution Plan Winner

被害者によって使用ncci_rcvd_listインデックスは、単一のキー列と複数含ま列にインデックスをカバーする非クラスタ化されています。それらの列の1つは勝者によって更新されます。キー列は更新されません。

mgs_listテーブルには、約500,000レコードがあります。 SELECTクエリによって返される結果セットは、通常、十数程度のようなわずかな行です(ただし、場合によっては数千にもなることがあります)。

この状況がどのようにデッドロックになるか説明できますか?

これは非常に頻繁に発生するプロダクションシステムからキャプチャされます。私はトランザクションの分離レベルをコミットされたスナップショットを読み取るように変更することでこれを解決しました。これはもはや問題ではありませんが、そこで何が起こったのかを理解し、問題の解決策があるかどうかを確認したいと思います。

+0

xmlとして実行プランを貼り付けて共有できます – TheGameiswar

答えて

2

Page 155679は、IXモードでprocess319282aca8(UPDATE)が所有し、process30aa42d468(SELECT)がSモードで必要です。ページ396658はSモードでSELECTによって所有されており、IXモードでUPDATEが必要です。

両方のクエリでインデックスに問題がありません。 UPDATEは索引を使用しますが、カバーしていないため、クラスタード索引へのRIDをルックアップする必要があります。 SELECTはスキャンです(ページ・レベルSロックによって与えられます)。これは並行性の下で保証されたデッドロックです。

これは、テーブルをキューとして誤って使用しているもう1つの例です。 Using tables as Queuesを読んでください。あなたの状態をあなたの出来事から分離してください。エンキューとデキューのみイベント

PS。 '被害者'は常にロールバックする作業が少ないトランザクションであり、読み取りと書き込みの両方でこれが常に読み取られます。また、あなたが投稿したSELECT実行計画が実際にデッドロックした計画であるかどうかは疑問です。

+1

ところで、そのテーブルにUPDATEトリガーがありますか? –

+0

はい、実際にはそのテーブルに単純な更新トリガーがあります。別のデータベースの統計表のレコードを更新します。それ以外の場合は、リンク先のドキュメントを読む...そのドキュメントに記載されていない限り、選択がスキャンであり、プランが「偽」であると思われる理由を説明できますか?結局、selectステートメントのカバーインデックスがあります。これは、そのクエリを手動で実行するたびに得られるプランです。 – IamNaN

+0

@RemusRusanu:実行スタックフレームからテーブル – TheGameiswar

関連する問題