複数のクライアントアプリがService Broker(ストアドプロシージャを使用)経由でメッセージを送信する状況があります。これらのメッセージは、さらに別のクライアントアプリによって取得され、処理されます。メッセージが取得される方法は、アプリが次のSQLステートメント(疑似コード)を発行することです。
LOOP {
WAITFOR (RECEIVE CONVERT(int, message_body) AS Message FROM SB_ReceiveQ)
ProcessMessage
}
したがって、基本的にコードはメッセージが受信されるまでブロックするだけです。これはすべて正常に動作します。
私の質問は、いくつかのService Brokerベースのリソースに基本的に永遠に掛かるWAITFOR (RECEIVE...
コマンドを発行する意味についてです。このパターンに関連して知っておくべきパフォーマンスの問題はありますか?
参考までに、これはSQL Server 2005です。
SQL Serverでワーカーをブロックしているため、ワーカーが制限されており、 最大ワーカースレッド の制約を受けます。つまり、WAITFOR(RECEIVE...)
で何千ものリクエストがブロックされてはいけません。そうすると、サーバーのワーカーが不足します。
しかし、最初に頭に浮かぶ質問は、Service Brokerのアクティベーションを活用しない理由ですか?この方法では、常に待機しているのではなく、受信するメッセージがあるためにアクティブ化されている場合のみ待機します。
SQL Server 2005では、毎日50台以上のマシンがこれを毎日実行しています。問題なく3年以上実行しています。
無期限のWAITFOR
に関して私が知っている最大の問題は、ログファイルの拡張です。これは説明 ここ です。 SQL Serverは、トランザクションを開始するとログにフックします。他のテーブルへのUPDATE
sなど、トランザクションの開始後に発生するすべてのトランザクションイベントは、その「後」のログに記録されます。 SQL Serverが循環的にログファイルに書き込むと考えることができます。最後に到達すると、最初に移動して続行します。ただし、ログが再利用できない「アクティブなトランザクション」でいっぱいになると、有効になっている場合はログの展開を開始する必要があります。
ログファイルの拡張にはコストがかかります。サーバーがクライアントに応答する前にログに記録する必要がある場合、それらの応答はログが拡張するまで待機する必要があります。さらに、トランザクションが永久に続く場合、ログは使用可能なすべての空き領域を使用するまで拡張されます。
RECEIVE
の実行にかかる限り、ログの再利用は防止されます。これを軽減するには、RECEIVE
のタイムアウトが十分に短いことを確認して、ログが無制限に大きくなるのを防ぎ、タイムアウトの時間内にイベントのエラー状態が処理されないようにします。