メッセージ交換グループのロック
Service Broker では、メッセージ交換グループのロックを使用して、関連する一連のメッセージが、常に 1 つのキュー リーダーで処理されることを保証しています。また、メッセージ交換グループのロックを使用して、メッセージが順序どおりに一度だけ処理されることも保証しています。
すべてのメッセージ交換は、メッセージ交換グループに属しています。各メッセージ交換は、既定では、異なるメッセージ交換グループに属しているので、異なるメッセージ交換グループ ID を持っています。MOVE CONVERSATION ステートメントは、メッセージ交換のメッセージ交換グループを変更します。BEGIN DIALOG CONVERSATION ステートメントには、新しいメッセージ交換を既存のメッセージ交換グループと関連付けるオプションが用意されています。メッセージ交換グループの詳細については、「メッセージ交換グループ」を参照してください。
メッセージ交換グループのロックを使用すると、同じメッセージ交換グループ ID を持つ一連のメッセージに排他ロックが設定されます。メッセージ交換グループのロックは、使いやすさ、効率のよさ、および正確さを実現することを念頭に置いてデザインされています。メッセージ交換グループのロックを取得または解放するための具体的なコマンドやヒントはありません。代わりに、対話またはメッセージ交換グループに影響のある Service Broker コマンドで、適切なメッセージ交換グループのロックが自動的に取得されます。たとえば、BEGIN DIALOG ステートメントでは、新しい対話が属するメッセージ交換グループをロックし、RECEIVE ステートメントでは、受信したメッセージが属するメッセージ交換グループをロックします。
セッションでは、メッセージ交換グループのロックは、セッションがロックを取得したトランザクションの実行中は保持されます。セッションでは、複数のトランザクション間でメッセージ交換グループのロックを保持することはできません。トランザクションが終了すると、トランザクションの実行中に取得されたメッセージ交換グループのロックはすべて解放されます。
ロックは、メッセージ交換 ID ではなく、メッセージ交換グループに対して行われます。そのため、メッセージ交換の発信側と発信先が同じデータベースに存在している場合でも、ロックはメッセージ交換の一方の側だけに設定されます。発信先のサービスで取得されたロックにより、発信側のサービスがブロックされることはありません。また、その逆の場合も同様です。さらに、データベース エンジンでは、着信メッセージをキューに追加するときにロックが設定されません。メッセージが属するメッセージ交換グループにメッセージ交換グループのロックが設定されている場合でも、データベース エンジンでは、メッセージがキューに追加されます。
つまり、実際、Service Broker から取得した ID のみを使用するアプリケーションでは、Service Broker リソースのロックを取得するまで待機する必要がありません。多くの Service Broker アプリケーションは、Service Broker によるロックを使用するようにデザインされています。ほとんどの Service Broker アプリケーションでは、同じトランザクション内で実行されている Service Broker ステートメントから取得したメッセージ交換グループ ID とメッセージ交換ハンドルのみを使用します。
たとえば、アプリケーションでは、通常、Service Broker からメッセージ交換グループ ID を取得し、状態テーブルから状態を取得して、そのメッセージ交換グループに属するメッセージ交換のメッセージを処理します。メッセージ交換グループ ID を取得すると、アプリケーションでは、そのメッセージ交換グループに対してロックを取得したことになります。他のアプリケーション インスタンスでは、そのメッセージ交換グループに対してロックを取得することはできません。ただし、メッセージ交換グループのロックは、他のアプリケーション インスタンスが、他のメッセージ交換グループのメッセージを受信することを妨げたり、キューに着信する着信メッセージを妨げたりするものではありません。
このロック方法により、Service Broker では、メッセージが順序どおりに処理されることが保証されます。特定のメッセージ交換グループのメッセージを処理できるのは 1 つのキュー リーダーだけなので、2 つのキュー リーダーが、同時に同じメッセージ交換グループのメッセージを受信することはありません。RECEIVE ステートメントでは、特定のメッセージ交換のメッセージをメッセージが送信された順序で返します。そのため、複数のキュー リーダーで、明示的にメッセージの順序を調整する必要なく、キューからメッセージを処理することができます。
ロックは個別のメッセージ交換ではなく、メッセージ交換グループに対して設定されるので、RECEIVE ステートメントで特定のメッセージ交換を指定しないキュー リーダーでは、同じメッセージ交換グループに属する別のメッセージ交換からメッセージを受信することがあります。さらに、RECEIVE ステートメントでは、現在のトランザクションでメッセージが属するメッセージ交換グループのロックが解除されているか、またはロックされているかどうかに関係なく、キュー内の次に使用可能なメッセージが返されます。特定のメッセージ交換からメッセージを受信するには、RECEIVE ステートメントでメッセージ交換ハンドルを指定します。特定のメッセージ交換グループからメッセージを受信するには、RECEIVE ステートメントでメッセージ交換グループ ID を指定します。
このロック方法により、アプリケーションでは、アプリケーションの状態テーブルを更新する前にメッセージ交換グループのロックを取得する必要があります。ほとんどの場合、アプリケーションがメッセージを受信するか、またはメッセージ交換グループを取得したときに、ロックは自動的に取得されます。ただし、エラー処理を行う際には、アプリケーションで、状態テーブルを更新してエラーを記録する前にメッセージ交換グループのロックの再取得が必要な場合があります。エラー処理の詳細については、「Service Broker のエラー処理」を参照してください。
次のステートメントでは、メッセージ交換グループのロックが取得されます。
- BEGIN DIALOG CONVERSATION (Transact-SQL)
- BEGIN CONVERSATION TIMER (Transact-SQL)
- GET CONVERSATION GROUP (Transact-SQL)
- END CONVERSATION (Transact-SQL)
- MOVE CONVERSATION (Transact-SQL)
- RECEIVE (Transact-SQL)
- SEND (Transact-SQL)
参照
その他の技術情報
データベース エンジンのロック
sys.conversation_endpoints (Transact-SQL)