SQL Server 2008 R2には、トランザクションを含むデータベース変更のタイムアウトを引き起こす方法はありますか?アプリケーションコードがハングまたは例外をスローし、ロールバックまたはコミットの実行に失敗するシナリオがあります。これにより、トランザクションが完了するまで他のセッションがハングします。
マークの答えを拡張しています...
クライアントタイムアウトイベントが発生すると(.net CommandTimeoutなど)、クライアントは "ABORT"をSQL Serverに送信します。その後、SQL Serverはクエリ処理を単に破棄します。トランザクションはロールバックされず、ロックは解放されません。
これで、接続は接続プールに返されるので、SQL Serverでは閉じられません。これが発生した場合(KILLまたはクライアントの再起動などを介して)、トランザクション+ロックはクリアされます。 sp_reset_connectionは、そうするようにアドバタイズされていても、クリアしないか、クリアしないことに注意してください。
このアボートによるデトリタスは他のプロセスをブロックします。
SQL Serverがトランザクション+クライアントタイムアウトのロック(厳密にはABORTイベント)をクリアする方法は、SET XACT_ABORT ONを使用することです。
SSMSで2つのクエリウィンドウを開いていることを確認できます。
ウィンドウ1:
メニューのQuery..Query Optionsで5秒のタイムアウトを設定し、これを実行します
BEGIN TRAN
UPDATE sometable WITH (TABLOCKX) SET foo = foo WHERE 1 = 0;
WAITFOR DELAY '00:00:10' -- just has to be longer then timeout
ウィンドウ2、これは永遠に待機します(またはタイムアウトに達します)
SELECT * FROM sometable
SET XACT_ABORT ONにも興味深い副作用があります。
これの組み合わせは、部分的なコミット/ロールバックにSAVEPOINTSを使用できないことを意味します(ただし、正確な動作は思い出せません)。どちらがいいですか
SET XACT_ABORTのSOリンク:
ネストされたストアドプロシージャ:
Sp_reset_connectionの場合:
問題の説明に100%となるのに十分な情報がないため、これはためらいがちで答えます。これが最善のアドバイスです。 「ハングまたはが例外をスローする」は、問題の原因が適切に理解されていないことを示しているため、注意して続行してください。
これに対する最も簡単な解決策は、おそらくSET XACT_ABORT ON
です。
XACT_ABORT
は、ランタイムエラーが発生した場合にSQL Serverがトランザクションをロールバックするかどうかを決定します。デフォルトのSET XACT_ABORT OFF
は、エラーを引き起こしたステートメントのみをロールバックし、親トランザクションは開いたままにします。
デフォルト設定の「問題」の副作用は、タイムアウトがまったく同じ問題を引き起こし、クライアントが処理およびロールバックを担当するオープントランザクションになる可能性があることです。クライアントがトライ/キャッチ/ロールバックを行わない場合、トランザクションはKILL <spid>
の超暴力に参加する(そして私が@gbnを引用する)まで、開いたままになります。
よく引用されている Erland Sommarskog'sSQL Serverでのエラー処理 に関する記事には、これらのシナリオなどに対処するために必要なすべての背景と戦略が含まれています。
編集(次のコメント):開いているトランザクションを特定するには、おそらく sp_whoisactive が最も機能が充実しています。