SQL Server 2008 R2には、トランザクションを含むデータベース変更のタイムアウトを引き起こす方法はありますか?アプリケーションコードがハングまたは例外をスローし、ロールバックまたはコミットの実行に失敗するシナリオがあります。これにより、トランザクションが完了するまで他のセッションがハングします。
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
は、エラーの原因となったステートメントのみがロールバックされ、親トランザクションは開いたままになります。
デフォルト設定の「問題」の副作用は、タイムアウトがまったく同じ問題を引き起こす可能性があることです。これは、クライアントが処理とロールバックを担当するオープントランザクションです。クライアントがtry / catch / rollbackを行わない場合、トランザクションはの超暴力に参加する(そして私が@gbnを引用する)まで、開いたままになりますKILL <spid>
。
SQL Serverでのエラー処理に関するErland Sommarskogのよく引用された記事には、これらのシナリオなどに対処するために必要なすべての背景と戦略が含まれています。
編集(次のコメント):開いているトランザクションを識別するには、sp_whoisactiveがおそらく最も機能が充実しています。