私たちが経験しているいくつかのブロックを追跡するのに本当に問題があります。
ルートブロッキングSPIDのステータスは「スリープ」、コマンドは「AWAITING COMMAND」、sqltext
はSET TRANSACTION ISOLATION LEVEL READ COMMITTED
。
ブロックされたトランザクション数別の上位トランザクションレポートを表示すると、ブロッキングSQLステートメントは「-」です。
SQLでトレースを実行し、ブロッキングが発生したときにルートブロッキングSPIDをトレースしましたが、実際にはどこにも誘導されていません。最後のtraceステートメントは、上記のsqltext
と同じですSET TRANSACTION ISOLATION LEVEL READ COMMITTED
。
TRY/CATCH BEGIN TRAN/COMMIT TRAN/ROLLBACK TRANステートメントがあることを確認するために、関連するすべてのストアドプロシージャをチェックしました(実行されるスタンドアロンステートメントがないように、すべてにストアドプロシージャを使用しています)。この問題は過去24時間に発生し始めたばかりで、システムに変更を加えたと主張している人はいません。
解決策:使用頻度の低いストアドプロシージャの1つに挿入のエラーがありました(列数が一致しませんでした)が、正確に何が起こっているのか混乱しています。
すべてのトレース情報を見ると、このストアード・プロシージャーのEXECステートメントが時々リストされていましたが、ブロックしているSPIDでBLOCKが発生する直前には決してありませんでした。ブロッキングが開始されたとき、トレースはその実行(またはその中のステートメントのいずれか)を記録していなかったようです。ただし、トレースがその実行を記録し、ブロッキングが発生しなかった場合もあります。
ストアドプロシージャのエラーレポートはユーザーからのものであり、トレースで複数のEXECステートメントを見つけて、SSMSで実行できました。私がそれらを実行したときに、ブロッキングが発生したり、ハングしたりすることはありませんでした。期待どおりに実行されました(catchブロックが起動し、エラーの後にトランザクションをロールバックしました)。ストアドプロシージャの修正を解決した後、問題は再び発生していません。
コメントから、SQLクエリを中止したクライアント側のコマンドタイムアウトがあったと思います。接続プールのためにSQL Serverで接続が開いたままになるため、これはトランザクションをロールバックしません。
したがって、SET XACT_ABORT ONを使用するか、クライアントのロールバックコードを追加する必要があります
詳細は SQL Server Transaction Timeout をご覧ください
Sys.dm_exec_connectionsのmost_recent_sql_handleを使用して、実行された最後のステートメントを確認します。
SELECT t.text,
QUOTENAME(OBJECT_SCHEMA_NAME(t.objectid, t.dbid)) + '.'
+ QUOTENAME(OBJECT_NAME(t.objectid, t.dbid)) proc_name,
c.connect_time,
s.last_request_start_time,
s.last_request_end_time,
s.status
FROM sys.dm_exec_connections c
JOIN sys.dm_exec_sessions s
ON c.session_id = s.session_id
CROSS APPLY sys.dm_exec_sql_text(c.most_recent_sql_handle) t
WHERE c.session_id = 72;--your blocking spid
そのspidの未処理のトランザクションがあるかどうかも確認してください
SELECT st.transaction_id,
at.name,
at.transaction_begin_time,
at.transaction_state,
at.transaction_status
FROM sys.dm_tran_session_transactions st
JOIN sys.dm_tran_active_transactions at
ON st.transaction_id = at.transaction_id
WHERE st.session_id = 72;--your blocking spid
Adam Machanicの sp_whoisactive を使ってみましたか?外部コマンドを取得して、それが本当にproc内にあるかどうかを確認するオプションがあります。アプリケーションがトランザクションをコミットせずに開いたままにしている可能性があります。 DBCC OPENTRAN も確認してください。