ユーザーが適切なパラメーターを選択して、実行に数分以上かかるクエリを実行する場合があるシナリオがあります。彼がそのようなパラメーターの組み合わせを選択するのを防ぐことはできないので(それは非常に合法です)、クエリにタイムアウトを設定したいと思います。
クエリの実行自体を停止し、トランザクションをロールバックしたいので注意してください。そうしないと、サーバーリソースのほとんどが占有されてしまいます。アプリケーションを再起動して組み合わせを再試行するせっかちなユーザーを追加すると、災害のレシピが得られます(SQL Server DoSを参照)。
これはどのように行うことができますか?
私の知る限り、クライアントでコマンドまたは接続のタイムアウトを設定する以外に、サーバーでクエリごとにタイムアウトを変更する方法はありません。
sp_configure
を使用して、デフォルトの600秒を実際に変更できますが、これらはサーバースコープです。
うーん! LOCK_TIMEOUTを試しましたか
クエリを実行する前に、元の状態を書き留めてください
クエリ用に設定します
クエリを実行した後、元の値に戻します
SET LOCK_TIMEOUT 1800;
SELECT @@LOCK_TIMEOUT AS [Lock Timeout];
私は2つのことを提案するかもしれません。
1)ロックを伴う可能性のある複数のテーブルを使用しているためにクエリに時間がかかる場合、非常に高速な解決策は、「NoLock」ヒントを使用してクエリを実行することです。
すべてのテーブル参照にSelect * from YourTable WITH (NOLOCK)
を追加するだけで、クエリが同時トランザクションをブロックするのを防ぐことができます。
2)すべてのクエリが(たとえば)5秒未満で実行されることを確認したい場合は、@ talhaが提案したものを追加できます。
実行の先頭に追加するだけです
SET LOCK_TIMEOUT 5000; --5 seconds.
そして、それはあなたのクエリが5未満かかるか失敗する原因になります。次に、例外をキャッチし、必要に応じてロールバックする必要があります。
それが役に立てば幸い。
それは建築上の問題のように聞こえます、そしてあなたがすることができるどんなタイムアウト/切断も多かれ少なかれバンドエイドでしょう。これは、SQLサーバー側で、読み取り専用レプリカ、トランザクションログ配布(接続する読み取り専用サーバーを提供するため)、レプリケーションなどによって解決する必要があります。基本的に、DMZ sqlサーバーに、大量の読み取りを実行しても、データを強制終了することはありません。これは非常に一般的です。適切に設計されたSQLシステムは、DDoSによって停止されません。ガスを踏むと死ぬ車のように。
とは言うものの、コードを自由に変更できる場合は、クエリが重すぎるかどうかを推測でき、ストアドプロシージャでX行のみを拒否または返すことができます。レポートツールなどに接続していて、それが生成するSELECTを制御できない場合は、ビューをポイントしてから、ビューで安全弁を実行できます。
また、最新の鮮度が重要ではなく、月次売上データのように妥協できる場合は、複雑な結合を回避するためにジョブごとに複雑な結合の物理テーブルをコンパイルすると、すべてがうまくいく可能性があります。クエリごとに1秒未満である。
それはあなたがしていることに完全に依存しますが、常に解決策があります。最適化するために追加のコーディングが必要な場合もあれば、セカンダリ読み取り専用DBを取得するために追加の費用がかかる場合もあります。また、インデックスの調整に時間と注意が必要な場合もあります。
ですから、それは完全に異なりますが、私は「何を妥協できるか、何を変えることができるか」から始めます。そこから行きます。
クエリが1つしかない場合、T-SQLレベルでタイムアウトを設定する方法がわかりません。
ただし、ストアドプロシージャ内にいくつかのクエリ(つまり、一時テーブルにデータを収集する)がある場合は、GETDATE()
、DATEDIFF()
、および各部分の実行時間を格納するいくつかのINT
変数。