Compartilhar via


Remover mensagens envenenadas

Aplica-se a:SQL ServerInstância Gerenciada de SQL do Azure

Uma mensagem venenosa é uma mensagem que contém informações que um aplicativo não pode processar com êxito. Por exemplo, uma estação de trabalho de fabricação pode enviar uma solicitação para retirar uma parte do inventário pouco antes que uma ordem de alteração torne a parte obsoleta. A ordem de alteração torna-se efetiva enquanto a solicitação do estoque está em trânsito. O aplicativo de gerenciamento de inventário recebe a solicitação da estação de trabalho, mas não consegue processar a solicitação com êxito e a operação de banco de dados para atualizar o número de partes no estoque falha. A transação que contém a operação de recebimento é, então, revertida, retornando a mensagem para a fila. Nessa situação, o aplicativo continua a receber a mesma mensagem, a atualização continua a falhar e a mensagem retorna à fila.

Uma mensagem de veneno não é uma mensagem corrompida e pode não ser uma solicitação inválida. O Service Broker contém verificações de integridade de mensagem que detectam mensagens corrompidas. Um aplicativo também geralmente valida o conteúdo de uma mensagem e descarta uma mensagem que contém uma solicitação ilegal. Em contrapartida, muitas mensagens suspeitas eram válidas quando a mensagem foi criada, mas depois se tornaram impossíveis de processar.

Detecção automática de mensagens de veneno

O Service Broker fornece detecção automática de mensagens suspeitas. Quando uma transação que contém uma RECEIVE instrução é revertida cinco vezes, o Service Broker desabilita todas as filas das quais a transação recebeu mensagens definindo automaticamente o status da fila como OFF. Além disso, o Service Broker gera um evento do tipo Broker:Queue Disabled.

Um administrador pode usar alertas do SQL Server Agent para ser notificado quando uma fila estiver desabilitada. Um desenvolvedor também pode criar um aplicativo que detecta quando uma fila for desabilitada pelo Service Broker. Esse aplicativo frequentemente inspeciona as mensagens na fila para localizar a mensagem suspeita. Depois que o aplicativo determina qual mensagem não pode ser processada, ele define o status da fila como ON e encerra a conversa para a mensagem com um erro. Um aplicativo que detecta as mensagens suspeitas deve ser criterioso ao limpar qualquer estado associado à conversa quando ela é encerrada. Para obter mais informações sobre como criar um aplicativo para se recuperar de mensagens suspeitas, consulte Manipular mensagens suspeitas.

Remover mensagens suspeitas administrativamente

A maioria dos aplicativos deve localizar e remover mensagens suspeitas programaticamente. No entanto, às vezes pode ser necessário remover uma mensagem de veneno manualmente. Por exemplo, a parte do aplicativo que executa a recuperação pode não ser capaz de detectar a mensagem de veneno ou pode não ser capaz de limpar com segurança o estado salvo para a conversa.

A remoção manual de uma mensagem corre o risco de interromper uma conversa importante. Portanto, sempre inspecione uma mensagem suspeita antes de removê-la da fila. Para verificar o conteúdo da mensagem, inicie a transação, receba e exiba o corpo da mensagem e, em seguida, reverta a transação. Até que você tenha certeza de que a mensagem em questão é uma mensagem venenosa, é importante reverter a transação.

Exemplo

O exemplo a seguir mostra como inspecionar uma mensagem com segurança no identificador de conversação e29059bb-9922-40f4-a575-66b2e4c70cf9 na fila ExpenseQueue. [!OBSERVAÇÃO] Os exemplos foram validados no SQL Server 2008 R2.
> Os exemplos de código neste artigo foram testados usando o AdventureWorks2025 banco de dados de exemplo, que pode ser baixado na home page de Exemplos do Microsoft SQL Server e Projetos da Comunidade .

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

Quando você localizar uma mensagem suspeita, encerre a conversa. O exemplo a seguir encerra a conversa 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

Quando uma conversa é encerrada, o Service Broker descarta as mensagens para essa conversa. O aplicativo que normalmente processa a mensagem não recebe uma mensagem EndDialog ou Error para esta conversa. Portanto, se o aplicativo mantiver o estado, você deve ser cuidadoso ao remover o estado associado à conversa após o encerramento desta com um erro.

Se um serviço não puder processar uma mensagem, isso significa que o serviço não pode concluir a tarefa para a conversa. Encerrar a conversa com um erro notifica o outro participante da conversa de que a tarefa falhou.