削除ステートメントのデッドロック


11

SQL Serverジョブを実行すると、デッドロックが発生します。デッドロックは、単純なDELETEステートメントで発生します。デッドロックを引き起こすためにSELECT / UPDATEクエリを実行する必要があると思いましたか?しかし、それはDELETE / DELETEデッドロックのように見えます...

私が探しているのは、DELETE / DELETEデッドロックが発生する理由です。(私の知る限りでは)異なるパラメーターを渡すことです。

何か案は?ありがとう。

deadlock-list
2014-05-20 07:30:09.66 spid25s      deadlock victim=process409048
2014-05-20 07:30:09.66 spid25s       process-list
2014-05-20 07:30:09.66 spid25s        process id=process409048 taskpriority=0 logused=0 waitresource=PAGE: 12:1:7127294 waittime=4352 ownerId=629860973 transactionname=DELETE lasttranstarted=2014-05-20T07:30:05.307 XDES=0x397219620 lockMode=U schedulerid=5 kpid=3792 status=suspended spid=150 sbid=0 ecid=3 priority=0 trancount=0 lastbatchstarted=2014-05-20T07:30:05.307 lastbatchcompleted=2014-05-20T07:30:05.307 clientapp=QSQL25 hostname=MORRIS hostpid=1528 isolationlevel=read committed (2) xactid=629860973 currentdb=12 lockTimeout=4294967295 clientoption1=671088672 clientoption2=128056
2014-05-20 07:30:09.66 spid25s         executionStack
2014-05-20 07:30:09.66 spid25s          frame procname=adhoc line=1 stmtstart=68 sqlhandle=0x020000000b887a18f75d0aa07c25a9b8630fca696aa0e5d2
2014-05-20 07:30:09.66 spid25s     DELETE FROM dbo.UserDetailsData WHERE        (Username = @P1) AND (UserDate = @P2)     
2014-05-20 07:30:09.66 spid25s          frame procname=unknown line=1 sqlhandle=0x000000000000000000000000000000000000000000000000
2014-05-20 07:30:09.66 spid25s     unknown     
2014-05-20 07:30:09.66 spid25s         inputbuf
2014-05-20 07:30:09.66 spid25s        process id=process432e08 taskpriority=0 logused=0 waitresource=PAGE: 12:1:7127916 waittime=2648 ownerId=629859744 transactionname=DELETE lasttranstarted=2014-05-20T07:30:04.833 XDES=0x4c3426b50 lockMode=U schedulerid=6 kpid=5988 status=suspended spid=146 sbid=0 ecid=3 priority=0 trancount=0 lastbatchstarted=2014-05-20T07:30:04.833 lastbatchcompleted=2014-05-20T07:30:04.820 clientapp=QSQL25 hostname=MORRIS hostpid=1528 isolationlevel=read committed (2) xactid=629859744 currentdb=12 lockTimeout=4294967295 clientoption1=671088672 clientoption2=128056
2014-05-20 07:30:09.66 spid25s         executionStack
2014-05-20 07:30:09.66 spid25s          frame procname=adhoc line=1 stmtstart=68 sqlhandle=0x020000000b887a18f75d0aa07c25a9b8630fca696aa0e5d2
2014-05-20 07:30:09.66 spid25s     DELETE FROM dbo.UserDetailsData WHERE        (Username = @P1) AND (UserDate = @P2)     
2014-05-20 07:30:09.66 spid25s          frame procname=unknown line=1 sqlhandle=0x000000000000000000000000000000000000000000000000
2014-05-20 07:30:09.66 spid25s     unknown     
2014-05-20 07:30:09.66 spid25s         inputbuf
2014-05-20 07:30:09.66 spid25s        process id=process39ea562c8 taskpriority=0 logused=0 waitresource=PAGE: 12:1:7127916 waittime=4352 ownerId=629860973 transactionname=DELETE lasttranstarted=2014-05-20T07:30:05.307 XDES=0x13e0e4b50 lockMode=U schedulerid=2 kpid=7124 status=suspended spid=150 sbid=0 ecid=1 priority=0 trancount=0 lastbatchstarted=2014-05-20T07:30:05.307 lastbatchcompleted=2014-05-20T07:30:05.307 clientapp=QSQL25 hostname=MORRIS hostpid=1528 isolationlevel=read committed (2) xactid=629860973 currentdb=12 lockTimeout=4294967295 clientoption1=671088672 clientoption2=128056
2014-05-20 07:30:09.66 spid25s         executionStack
2014-05-20 07:30:09.66 spid25s          frame procname=adhoc line=1 stmtstart=68 sqlhandle=0x020000000b887a18f75d0aa07c25a9b8630fca696aa0e5d2

5
いいえ、SELECT / UPDATE以外の他のシナリオでデッドロックが発生する可能性があります。本当に必要なのは2つのプロセスだけで、それぞれが他方が保持しているリソースが必要です。(1)DELETEステートメントはより大きなトランザクションの一部ですか?(2)行き詰まったエラーログテキストの代わりに、デッドロックXMLをどこかに投稿できますか?
アーロンバートランド

dbo.UserDetailsDataすべてのインデックスを含むテーブルスキーマを投稿していただけませんか?また、それらのステートメントが同じパラメーターで呼び出されているかどうかを知っていますか?どちらも使用されているログがゼロであることを考えると、お互いを踏んでいるので、コールをシリアル化するだけでよいのかと思います。
Jon Seigel、

XMLを取得するにはどうすればよいですか?SQL Serverエラーログからエラーを取得しました。ステートメントは異なるパラメーターで呼び出されます。最近、UserDateフィールドでフィルター処理するフィルター処理されたインデックスをいくつか追加しました。
K09 2014年

プロファイラーでデッドロックグラフイベントをキャッチします。次に、それをキャッチした後、行を右クリックして、>イベントデータを抽出し、どこかに.xdlとして保存し、そのコンテンツ(xmlです)をPastebin(または同様の場所)に投稿します。
マリアン

1
こんにちは、XMLがここに投稿されました... dl.dropboxusercontent.com/u/16953128/DeadlockTest.xdl
K09

回答:


14

私が探しているのは、DELETE / DELETEデッドロックが発生する理由です。

デッドロックは次の理由で発生するようです。

  1. spid 54 ecid 0更新(U)ページロックを取得するPAGE: 12:1:5147422
  2. spid 166 ecid 3U同じページの更新()ページロックを要求し、ブロックされます
  3. spid 54 ecid 2U同じページの更新()ページロックを要求します...

クエリによってページがプリフェッチされ、更新ロックがによって取得されecid 0ます。それが上記のステップ1です。手順3では、同じ並列クエリ(ecid 2)の子スレッドが同じロックを要求します。通常、これは問題にはなりません。SQL Server は、同じ親プロセスのスレッドを認識してecid 0おりecid 2、そのスレッドです。残念ながら、ステップ2はこれを妨げ、デッドロックが発生します。

とはいえ、デッドロックが発生する理由をあまり気にする必要はありません。重要な問題は、それをどのように回避するかです。その答えは、に効率的なアクセスパスを提供することですDELETE。ステートメントは行を検索WHERE Username = @P1 AND UserDate = @P2する必要があるため、これらの列にキー付けされたインデックスが必要です。

そしてもちろん、あなたはそのようなインデックスを持っています。本当の問題は、あなたの問題は、あなたがフィルターのインデックスを追加した後に発生始めた理由です。

その答えは、削除するフィルター処理されたインデックス行を見つける(およびその述語をチェックする)ために追加の列情報が必要であるということです。クエリでナロー/ロー単位の実行プランを使用する場合、ワイド/インデックス単位のプランとは異なり、実行エンジンはクラスター化インデックス削除演算子で追加の列をフェッチできません。

詳細と実際の例については、このブログ投稿をご覧ください。

この場合、列情報は計画の一部であるクラスタードインデックス削除の右側から取得する必要があるため、並列クラスタードインデックススキャンが使用されるため、デッドロックの可能性が高い低速のクエリになります。

答えは、次のいずれかを実行することです。

  1. フィルターされたインデックスを削除する
  2. フィルターされたインデックスキー/インクルード/述語列を既存の名前/日付インデックスに追加する
  3. ワイドアップデートプランを強制します(これをサポートする方法はありません)
  4. スナップショット分離(RCSIではない)でクエリを実行する

オプション2は私の好みです。

オプション4(Jack Douglasに感謝)にはデッドロックを取り除く利点があり、変更の素性を考えると「更新の競合」を引き起こすべきではありませが、データベースレベルでスナップショット分離を有効にし、分離レベルを明示的に変更する必要があります。そして根本的な問題を解決しません:あなたはまだ素敵なインデックスが求めて無駄なパラレル表スキャン、で終わるだろうあなたが本当に欲しいものです。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.