ブロッキングの原因となったクエリを効果的に特定するルーチンが必要です。これは私の前の質問に関連しています まだロックを保持しているクエリを見つける方法は? 。
私はこれに関してオンラインでたくさんの資料があることを知っていますが、それらはすべて、アクティブなセッションの最後のSQLステートメントがロックを獲得した(つまり、ブロッキングを生成した)ものであるという前提に基づいています。 true(私の場合、決して)。
blocking-process-threshold
を30秒に設定して、ブロッキングプロセスレポート(BPR)の分析を開始しました。
これらのレポートは、しきい値に達すると、ブロッキングが発生するたびに起動されます。
ブロックされたspidおよびブロックされたspidに関する情報が含まれています。
多くの場合、ブロッキングspidはいくつかのステートメントafterを実行し、リソース(テーブル、ページ、または行)を取得してロックを保持しているステートメントを実行します。レポートコンテンツの中で、どのクエリがそのブロックを正確に引き起こしたかについては、私は無知のままです。
通常、SQL Server DMVは各session_id
の最後のSQLテキストのみを表示し、アクティブなロックに関連するDMV(sys.dm_tran_locks
など)もこの問題に対処していません。
ブロックされたクエリの調整は、ここでの最良のアプローチではありません。アプリケーションはすべてクライアントコードに埋め込まれた動的SQLに基づいており、ストアドプロシージャを使用せず、これまでに見たブロッキングに基づいており、すべてのブロックされたクエリは正しくインデックス化されていましたそして書かれた。
これを解決するオプションは、candidateクエリを収集することだと思います。これにより、ブロッキングが生成され、BPRで収集されたタイムスタンプとspidを使用してこの情報が検索されます。同意しますか?もしそうなら、あなたはxEventsを使用して可能な限り最小限のオーバーヘッドでこれを行う方法を指摘できますか?
XEventsセッションを使用して、長時間実行されるセッションを探すことをお勧めします。
あなたが説明している問題は、効率的なセットベースを使用する代わりに、行ごとの行( [〜#〜] rbar [〜#〜] )処理を実行するクライアントコードがあるように聞こえますアプローチ。
適切に設計されていないクライアントアプリケーションは、次のようなことを行う場合があります。
何が起こるべきかは次のとおりです:
SQL Serverの回避策は、スナップショット分離行のバージョン管理を使用して実装できます。詳細は このTechnetドキュメント を参照してください。基本的に、行のバージョン管理により、ライターはリーダーをブロックせず、ブロックを大幅に削減できます。
DMVからブロッキング情報を取得できます。
select getdate() Run_Date,
r.session_id,
r.blocking_session_id,
st.text SQL_Text
from sys.dm_exec_requests r
cross apply sys.dm_exec_sql_text(r.sql_handle) st
where r.blocking_session_id <> 0
or r.session_id in( select r2.blocking_session_id
from sys.dm_exec_requests r2
where r2.blocking_session_id <> 0)
選択した待機時間でループ内で実行し、結果をテーブルに出力できます。
システムが遭遇するすべてのブロックをキャプチャするわけではありませんが、多くのブロッキングが発生している場合は、トラブルシューティングを開始するのに十分な程度にピックアップする必要があります。