Suppression des messages incohérents

Un message incohérent est un message qui contient des informations dont le traitement ne peut pas être correctement effectué par une application. Ainsi, un poste de fabrication peut soumettre une demande de pièce auprès du stock juste avant qu'un changement de commande ne rende la pièce demandée 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 du stock reçoit la demande en provenance de la station de travail, mais elle est dans l'incapacité de la traiter et l'opération de base de données pour mettre à jour le nombre de pièces 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 incohérent n'est pas un message endommagé et sa demande n'est pas forcément erronée. 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 contenant une instruction RECEIVE est restaurée cinq fois, Service Broker désactive toutes les files d'attente qui ont envoyé les messages reçus par la transaction. Pour cela, il définit automatiquement l'état de chaque file d'attente sur OFF. Par ailleurs, Service Broker génère un événement de type Broker:Queue Disabled.

Un administrateur peut utiliser les alertes de l'Agent SQL Server pour être prévenu de la désactivation d'une file d'attente. 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 qu'elle a déterminé le message impossible à traiter, l'application définit l'état de la file d'attente sur ON et met fin à la conversation pour ce message par le biais d'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 permettant une récupération suite à des messages incohérents, consultez Gestion des messages incohérents.

Suppression des messages incohérents par voie administrative

La plupart des applications doivent assurer le repérage et la suppression des messages incohérents par programmation. Toutefois, il demeure quelquefois nécessaire de supprimer manuellement un message incohérent. En effet, la partie de l'application qui effectue la récupération peut ne pas être en mesure de détecter un message incohérent ou être incapable de nettoyer de façon suffisamment approfondie l'état sauvegardé 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. Il est important de procéder à la restauration de la transaction tant que vous n'êtes pas certain de l'incohérence du message.

Exemple

L'exemple suivant illustre l'inspection sans risque d'un message pour le handle de conversation e29059bb-9922-40f4-a575-66b2e4c70cf9 dans la file d'attente ExpenseQueue.

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 VARBINARY(MAX),
          @validation 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. Remarquez que l'application normalement chargée du traitement du message ne reçoit pas de message EndDialog ni Error 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 est incapable de traiter un message, cela signifie qu'il est incapable d'exécuter la tâche pour 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é.