Supprimer les messages incohérents

S’applique à :SQL ServerAzure SQL Managed Instance

Un message empoisonné est un message contenant des informations qu’une application ne peut pas traiter correctement. Par exemple, une station de travail de fabrication peut soumettre une demande de retrait d’une partie de l’inventaire juste avant qu’une commande de modification rend la partie obsolète. La modification de commande est intégrée et devient effective alors que la demande de retrait auprès du stock est en transit. L’application de gestion de l’inventaire reçoit la demande de la station de travail, mais ne peut pas traiter correctement la demande, et l’opération de base de données pour mettre à jour le nombre de parties en stock échoue. La transaction contenant l'opération de réception est alors restaurée, ce qui renvoie le message dans la file d'attente. Dans cette situation, l'application continue de recevoir le même message, la mise à jour multiplie les échecs et le message est renvoyé dans la file d'attente.

Un message empoisonné n’est pas un message endommagé et n'est peut-être pas une requête non valide. Service Broker contient une fonction de contrôle de l'intégrité des messages qui permet de détecter les messages endommagés. En général, une application valide le contenu d'un message et ignore les messages dont les demandes sont illégales ; ce n'est pas le cas des messages incohérents puisque bon nombre de ces messages sont valides au moment de leur création, leur traitement est seulement devenu impossible par la suite.

Détection automatique des messages incohérents

Service Broker propose une fonction de détection automatique des messages incohérents. Lorsqu’une transaction qui contient une RECEIVE instruction échoue cinq fois, Service Broker désactive toutes les files d’attente à partir desquelles la transaction a reçu des messages en définissant automatiquement l’état de la file d’attente sur OFF. De plus, Service Broker génère un événement de type Broker :Queue Disabled.

Un administrateur peut utiliser des alertes SQL Server Agent pour être averti lorsqu’une file d’attente est désactivée. Un développeur peut également créer une application qui détecte les files d'attente désactivées par Service Broker. Cette application inspecte souvent les messages d'une file d'attente à la recherche d'un message incohérent. Une fois que l’application détermine quel message ne peut pas être traité, l’application définit l’état ON de la file d’attente et met fin à la conversation du message avec une erreur. Une application qui détecte les messages incohérents doit procéder à un nettoyage scrupuleux de tout état associé à la conversation lorsqu'elle met un terme à cette conversation. Pour plus d’informations sur la création d’une application pour gérer la récupération des messages empoisonnés, consultez Gérer les messages empoisonnés.

Supprimer les messages empoisonnés administrativement

La plupart des applications doivent assurer le repérage et la suppression des messages incohérents par programmation. Toutefois, il peut parfois être nécessaire de supprimer manuellement un message empoisonné. Par exemple, la partie de l’application qui effectue la restauration pourrait ne pas être en mesure d'identifier le message empoisonné ou de nettoyer en toute sécurité l’état enregistré pour la conversation.

La suppression manuelle d'un message présente le risque d'interrompre une conversation importante. Ainsi, l'inspection d'un message incohérent est incontournable avant de le supprimer de la file d'attente. Pour afficher le contenu du message, lancez une transaction, recevez le corps du message, affichez-le, puis restaurez la transaction. Jusqu'à ce que vous soyez certain que le message en question est un message empoisonné, il est important d'annuler la transaction.

Exemple

L’exemple suivant montre comment inspecter un message de façon sécurisée pour le handle de conversation e29059bb-9922-40f4-a575-66b2e4c70cf9 dans la file d’attente ExpenseQueue.>
> Les exemples de code de cet article ont été testés à l’aide de l’exemple AdventureWorks2025 de base de données, que vous pouvez télécharger à partir de la page d’accueil microsoft SQL Server Samples and Community Projects .

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

Lorsque vous trouvez un message incohérent, mettez un terme à la conversation. L’exemple suivant met fin à la conversation 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

Lorsqu'une conversation s'achève, Service Broker ignore les messages pour cette conversation. L’application qui traite normalement le message ne reçoit pas de message d’erreur ou EndDialog pour cette conversation. Si l'application gère l'état, vous devez donc faire attention à bien supprimer l'état associé à la conversation après avoir terminé la conversation au moyen d'une erreur.

Si un service ne peut pas traiter un message, cela signifie que le service ne peut pas effectuer la tâche de la conversation. En achevant la conversation par le biais d'une erreur, vous prévenez l'autre participant de la conversation que l'accomplissement de la tâche a échoué.