web-dev-qa-db-ja.com

SQL Serverトランザクションタイムアウト

SQL Server 2008 R2には、トランザクションを含むデータベース変更のタイムアウトを引き起こす方法はありますか?アプリケーションコードがハングまたは例外をスローし、ロールバックまたはコミットの実行に失敗するシナリオがあります。これにより、トランザクションが完了するまで他のセッションがハングします。

9

マークの答えを拡張しています...

クライアントタイムアウトイベントが発生すると(.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にも興味深い副作用があります。

  • 暗黙的なロールバックで@@ TRANCOUNTがゼロに設定されますが、エラー266は抑制されます(これは、@@ TRANCOUNTがストアドプロシージャの入り口と出口で異なる場合に発生します)
  • XACT_STATEは-1( "doomed")になります

これの組み合わせは、部分的なコミット/ロールバックにSAVEPOINTSを使用できないことを意味します(ただし、正確な動作は思い出せません)。どちらがいいですか

SET XACT_ABORTのSOリンク:

ネストされたストアドプロシージャ:

Sp_reset_connectionの場合:

20
gbn

問題の説明に100%となるのに十分な情報がないため、これはためらいがちで答えます。これが最善のアドバイスです。 「ハングまたはが例外をスローする」は、問題の原因が適切に理解されていないことを示しているため、注意して続行してください。

これに対する最も簡単な解決策は、おそらくSET XACT_ABORT ONです。

XACT_ABORTは、ランタイムエラーが発生した場合にSQL Serverがトランザクションをロールバックするかどうかを決定します。デフォルトのSET XACT_ABORT OFFは、エラーを引き起こしたステートメントのみをロールバックし、親トランザクションは開いたままにします。

デフォルト設定の「問題」の副作用は、タイムアウトがまったく同じ問題を引き起こし、クライアントが処理およびロールバックを担当するオープントランザクションになる可能性があることです。クライアントがトライ/キャッチ/ロールバックを行わない場合、トランザクションはKILL <spid>の超暴力に参加する(そして私が@gbnを引用する)まで、開いたままになります。

よく引用されている Erland Sommarskog'sSQL Serverでのエラー処理 に関する記事には、これらのシナリオなどに対処するために必要なすべての背景と戦略が含まれています。

編集(次のコメント):開いているトランザクションを特定するには、おそらく sp_whoisactive が最も機能が充実しています。

11