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


9

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

回答:


20

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

クライアントタイムアウトイベント(.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の場合:


未来はこんにちは!「sp_reset_connectionは、そのようにアドバタイズされているとはいえ、クリアしないか、クリアしないことに注意してください。」-SQL Serverの最新バージョンでは、これはもう当てはまらないと思いますか?
kamilk

11

あなたの問題の説明に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がおそらく最も機能が充実しています。


私は、いくつかのグーグルで、ハングが発生したときに開いているトランザクションを見つける方法を見つけました。おそらくこれが最善の解決策です。それは、コードで閉じられていないトランザクションの原因を見つけ、コードの穴を修正することです。他の参照用。DBCC OPENTRANは最も古いアクティブなトランザクションを返します-> msdn.microsoft.com/en-us/library/ms182792.aspxまたはこれに似たものは何ですか?- > weblogs.sqlteam.com/mladenp/archive/2008/04/29/...
デヴィッド・グレイライト

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.