web-dev-qa-db-ja.com

他のトランザクションをブロックするスリープSPID

私たちが経験しているいくつかのブロックを追跡するのに本当に問題があります。

ルートブロッキングSPIDのステータスは「スリープ」、コマンドは「AWAITING COMMAND」、sqltextSET 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ブロックが起動し、エラーの後にトランザクションをロールバックしました)。ストアドプロシージャの修正を解決した後、問題は再び発生していません。

16
Brad

コメントから、SQLクエリを中止したクライアント側のコマンドタイムアウトがあったと思います。接続プールのためにSQL Serverで接続が開いたままになるため、これはトランザクションをロールバックしません。

したがって、SET XACT_ABORT ONを使用するか、クライアントのロールバックコードを追加する必要があります

詳細は SQL Server Transaction Timeout をご覧ください

10
gbn

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
9
Sebastian Meine

Adam Machanicの sp_whoisactive を使ってみましたか?外部コマンドを取得して、それが本当にproc内にあるかどうかを確認するオプションがあります。アプリケーションがトランザクションをコミットせずに開いたままにしている可能性があります。 DBCC OPENTRAN も確認してください。