適用対象:SQL Server
Azure SQL Managed Instance
有害メッセージは、アプリケーションが正常に処理できない情報を含むメッセージです。 たとえば、製造ワークステーションは、変更注文によって部品が古くなる直前に、部品を在庫から引き出す要求を送信する場合があります。 変更オーダーは、在庫に対する要求が転送されている間に有効になります。 在庫管理アプリケーションはワークステーションから要求を受け取りますが、要求を正常に処理できず、在庫の部品数を更新するデータベース操作は失敗します。 受信操作を含んだトランザクションはロールバックされ、メッセージはキューに戻されます。 この状況では、アプリケーションは同じメッセージを受信し続け、更新は失敗し続け、メッセージはキューに戻されます。
有害メッセージは破損したメッセージではなく、無効な要求ではない可能性があります。 Service Broker には、破損したメッセージを検出するためのメッセージの整合性チェックが含まれています。 また通常、アプリケーションはメッセージの内容も検証し、無効な要求を含んだメッセージは破棄します。 一方、多くの有害なメッセージは、そのメッセージの作成時には有効だったものが、後に処理できなくなったものです。
有害メッセージの自動検出
Service Broker では、有害なメッセージの自動検出が提供されます。
RECEIVE ステートメントを含むトランザクションが 5 回ロールバックされると、Service Broker は、キューの状態をOFFに自動的に設定することで、トランザクションがメッセージを受信したすべてのキューを無効にします。 さらに、Service Broker は Broker :Queue Disabled 型のイベントを生成します。
管理者は、SQL Server エージェントアラートを使用して、キューが無効になったときに通知を受け取る場合があります。 開発者は、Service Broker がキューを無効にした際に、それを検出するアプリケーションを作成することもできます。 そのアプリケーションは、キュー内のメッセージを頻繁に検査して、有害なメッセージを検出します。 処理できないメッセージがアプリケーションによって判断されると、アプリケーションはキューの状態を ON に設定し、メッセージの会話をエラーで終了します。 有害なメッセージを検出するアプリケーションは、メッセージ交換を終了する際に、そのメッセージ交換に関連するすべての状態を慎重にクリーンアップする必要があります。 有害メッセージから回復するアプリケーションの作成の詳細については、「有害メッセージの 処理」を参照してください。
有害メッセージを管理的に削除する
ほとんどのアプリケーションは、有害なメッセージをプログラムを使用して追跡および削除します。 ただし、有害メッセージを手動で削除することが必要になる場合があります。 たとえば、回復を実行するアプリケーションの一部が有害メッセージを検出できない場合や、会話の保存された状態を安全にクリーンアップできない場合があります。
メッセージを手動で削除すると、重要なメッセージ交換を中断する危険性があります。 そのため、有害なメッセージをキューから削除する前に、必ずそのメッセージを検査してください。 メッセージの内容を確認するには、トランザクションを開始し、メッセージ本文を受信して表示し、トランザクションをロールバックします。 問題のメッセージが有害メッセージであることを肯定するまでは、トランザクションをロールバックすることが重要です。
例
次のサンプルは、会話ハンドル e29059bb-9922-40f4-a575-66b2e4c70cf9 のメッセージをキュー ExpenseQueue 内で安全に検査する方法を示しています。> [!ノート/メモ]
> この記事のコード サンプルは、AdventureWorks2025 サンプル データベースを使用してテストされました。このデータベースは、Microsoft SQL Server サンプルとコミュニティ プロジェクト ホーム ページからダウンロードできます。
USE AdventureWorks2008R2;
GO
-- Sample to show the content of a message, then return
-- the message to the queue. This may be useful to determine
-- whether a specific message cannot be processed due to the
-- content of the message.
-- Every exit path from the transaction rolls back the transaction.
-- This code is intended to inspect the message, not remove the
-- message from the queue permanently. The transaction must roll
-- back to return the message to the queue.
BEGIN TRANSACTION;
-- To print the body, the code needs the message_body and
-- the encoding_format.
DECLARE @messageBody AS VARBINARY (MAX),
@validation AS NCHAR;
-- Receive the message. The WAITFOR handles the case where
-- an application is attempting to process the message when
-- this batch is submitted. Replace the name of the queue and
-- the conversation_handle value.
WAITFOR (RECEIVE TOP (1)
@messageBody = message_body,
@validation = validation
FROM dbo.ExpenseQueue
WHERE CONVERSATION_HANDLE = 'e29059bb-9922-40f4-a575-66b2e4c70cf9'),
TIMEOUT 2000;
-- Roll back and exit if the message is not available
-- in two seconds.
IF @@ROWCOUNT = 0
BEGIN
ROLLBACK TRANSACTION;
PRINT 'No message available.';
RETURN;
END
-- Print the message based on the encoding format of
-- the message body.
IF (@validation = 'E')
BEGIN
PRINT 'Empty message.';
END
ELSE IF (@validation = 'X')
BEGIN
PRINT CONVERT (NVARCHAR (MAX), @messageBody);
END
ELSE IF (@validation = 'N')
BEGIN
PRINT 'No validation -- binary message:';
PRINT @messageBody;
END
ROLLBACK TRANSACTION;
GO
有害なメッセージを検出したら、メッセージ交換を終了します。 次の例では、会話 e29059bb-9922-40f4-a575-66b2e4c70cf9 を終了します。
-- End the conversation. Do this only if the message cannot be
-- processed by the normal procedure.
END CONVERSATION 'e29059bb-9922-40f4-a575-66b2e4c70cf9'
WITH ERROR = 127 DESCRIPTION = N'Unable to process message.';
GO
メッセージ交換を終了すると、Service Broker はそのメッセージ交換のメッセージを破棄します。 通常メッセージを処理するアプリケーションは、この会話の EndDialog または エラー メッセージを受け取りません。 そのため、アプリケーションが状態を維持している場合、メッセージ交換をエラーで終了した後、メッセージ交換に関連付けられている状態を慎重に削除する必要があります。
サービスがメッセージを処理できない場合は、サービスが会話のタスクを完了できないことを意味します。 メッセージ交換がエラーで終了すると、メッセージ交換の他の参加者に対して、タスクが失敗したことが通知されます。