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


16

私が経験しているいくつかのブロッキングを追跡するのに本当に苦労しています。

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


ブロッキングSPIDのホスト名はまったく役に立たないと思いますか?
ジョンセイゲル

いいえ、それは私たちのウェブサーバーの1つのIPです...ログイン/登録プロセス中に各SPROCコールのすべてのSQLログインを変更する別のアイデアがあります(エラーが発生していると感じています)どのSPROCがブロッキングを引き起こしているのかを特定するのに役立ちます。
ブラッド

1
TRY / CATCHはコンパイルエラーをキャッチせず、不一致の列挿入はそのようなコンパイルエラーになります。これにより、XX:Completedプロファイラーイベントの多くがトリガーされることもありません。
レムスルサヌ

1
天才開発者がINSERT INTO [table] SELECT * from [othertable]を使用し、ピアでキャッチされなかったため、この場合、実際にはコンパイルエラーではありません。ColdFusionから開発のSPROCを3回の同時セッションで1000回実行しましたが、実稼働環境のようにトランザクションを開いたままにすることはありませんでした。
ブラッド

回答:


10

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

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

参照してください。SQL Serverのトランザクション・タイムアウトのすべての血みどろの詳細については、


すべてのSPROCには、TRY / CATCHブロックとBEGIN TRAN / COMMIT TRAN / ROLLBACK TRANステートメントが含まれています。ROLLBACKはCATCHにあります。XACT_ABORTは引き続き効果がありますか?
ブラッド

@ブラッド:はい。リンクをご覧ください。CommandTimeoutでcatchブロックがヒットしない
-gbn

gbn:ありがとう。私はまだ混乱しています。接続はタイムアウトしないように設定されています(0)。したがって、接続を再利用し、接続がエラーのあるSPROC(TRY / CATCHおよびTRANブロックを含む)を実行すると、CATCHブロックでROLLBACKを実行することは決してできないため、テーブルをロックしてトランザクションを維持できます開いた?それは私には意味がありません。
ブラッド

@Brad:エラーのあるSPROCがCATCHブロックにヒットします。私は別のことを言ったり、違うとは言わなかった。しかし、私のリンクには、ConnectionTimeoutとは異なるCommandTimeoutがある場合に何が起こるかが示されています。クライアントは「中止」と言い、SQL Serverは処理を停止します。エルゴ、CATCHブロックまたはロールバックまたはコミットがヒットしない
-gbn

CommandTimeoutが指定されているとは思わない。すべてのストアドプロシージャはsqlstressを使用してテストしており、10ユーザー10回(少なくとも)で1000ms未満で実行する必要があります。私はまだ何が起こったのか非常に混乱していますが、問題を発見したことで質問を更新しています。
ブラッド

9

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

を使用DBCC INPUTBUFFER(spid)して、最後に実行されたSQLを確認することもできます。
マイクファル

私はそれらすべてを使用しましたが、最後のコマンドは常に元の投稿に書いたものです:SET TRANSACTION ISOLATION LEVEL READ COMMITTED。また、DBCC OPENTRANを実行しましたが、ブロッキングPIDのオープントランザクションがあることがわかります。
ブラッド

ステートメントが実際にプロシージャの一部である場合、最初のselectはプロシージャ名も提供します。
セバスチャンマイネ

Webサーバーからアドホッククエリを使用しないことを保証します。最初のクエリを実行すると、WHERE句がなくても、少数のSQLセッションで名前付きSPROCのみを取得し、残りの列はNULLです。
ブラッド

「トランザクション分離レベルの読み取りをコミットしました」というセッションがたくさんあり、それらはすべてColdFusion(Webサーバーで使用されるメインスクリプト)からのものです。おそらく、ColdFusionは、アイドル時にそのステートメントを発行して接続を開いたままにします(接続を開いたままにするように設定されているため)。
ブラッド

4

Adam Machanicのsp_whoisactiveを使用してみましたか?外部コマンドを取得して、それが実際にプロシージャ内にあるかどうかを確認するオプションがあります。アプリケーションがトランザクションをコミットする代わりに開いたままにしている可能性があります。DBCC OPENTRANご覧ください。


DBCC OPENTRANに感謝します。ブロッキングPIDには開いているトランザクションがあることはわかりますが、詳細はありません。sp_whoisactiveは、ブロックされたプロセスについて、自分で取得できるのと同じ情報を返します。「SET SET TRANSACTION ISOLATION LEVEL READ COMMITTED」以外の状況についてはまだ詳細がありません
ブラッド
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.