Quitar mensajes dañados
Un mensaje dañado es un mensaje que contiene información que una aplicación no puede procesar correctamente. Por ejemplo, una estación de trabajo de fabricación puede presentar una solicitud para retirar una parte del inventario justo antes de que una orden de cambio determine que la pieza está obsoleta. La orden de cambio se activa mientras la solicitud de inventario está en tránsito. La aplicación de administración de inventario recibe la solicitud de la estación de trabajo pero no puede procesarla correctamente por lo que la operación de base de datos para actualizar el número de piezas en las existencias genera un error. La transacción que contiene la operación de recepción se revierte y devuelve el mensaje a la cola. En esta situación, la aplicación recibe el mismo mensaje, la actualización vuelve a generar un error y el mensaje vuelve a la cola.
Un mensaje dañado no es un mensaje incorrecto y puede que no sea una solicitud no válida. Service Broker contiene comprobaciones de integridad de mensajes que detectan mensajes incorrectos. También las aplicaciones suelen validar el contenido de un mensaje y descartan los que contienen una solicitud no permitida. Por otra parte, muchos mensajes dañados eran válidos cuando se crearon pero, más tarde, se volvieron imposibles de procesar.
Detección automática de mensajes dañados
Service Broker proporciona detección automática de mensajes dañados. Cuando una transacción que contiene una instrucción RECEIVE se revierte cinco veces, Service Broker deshabilita todas las colas desde las que la transacción recibe mensajes mediante el establecimiento automático del estado de la cola en OFF. Además, Service Broker genera un evento de tipo Broker:Queue Disabled.
Un administrador puede utilizar alertas del Agente SQL Server para que se notifique la deshabilitación de una cola. Un programador también puede crear una aplicación que detecte cuándo Service Broker deshabilita una cola. Esta aplicación inspecciona a menudo los mensajes de la cola para encontrar el mensaje dañado. Una vez que determina qué mensaje no se puede procesar, establece el estado de la cola en ON y finaliza la conversación para el mensaje con un error. Una aplicación que detecta mensajes dañados debe limpiar cualquier estado asociado con la conversación cuando la finaliza. Para obtener más información sobre cómo crear una aplicación para establecer una recuperación después de mensajes dañados, vea Handling Poison Messages.
Quitar mensajes dañados mediante administración
La mayoría de las aplicaciones deben realizar un seguimiento y eliminar mensajes dañados mediante programación. Sin embargo, en ocasiones puede ser necesario eliminar un mensaje dañado manualmente. Por ejemplo, puede que la parte de la aplicación que realiza la recuperación no pueda detectar el mensaje dañado o limpiar de forma segura el estado guardado de la conversación.
Si se quita un mensaje de forma manual se corre el riesgo de interrumpir una conversación importante. Por tanto, siempre debe inspeccionar un mensaje dañado antes de quitarlo de la cola. Para ver el contenido del mensaje, inicie una transacción, reciba el cuerpo del mensaje, muestre el cuerpo del mensaje y, a continuación, revierta la transacción. Hasta que esté seguro de que el mensaje en cuestión es un mensaje dañado, es preferible revertir la transacción.
Ejemplo
En el siguiente ejemplo se muestra cómo inspeccionar un mensaje de forma segura para el identificador de conversación e29059bb-9922-40f4-a575-66b2e4c70cf9
de la cola ExpenseQueue
.
use AdventureWorks ;
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 ;
-- Rollback 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
Cuando encuentra un mensaje dañado, finaliza la conversación. En el siguiente ejemplo se finaliza la conversación 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
Cuando una conversación finaliza, Service Broker descarta los mensajes de esa conversación. Observe que la aplicación que suele procesar el mensaje no recibe ningún mensaje EndDialog ni Error para esta conversación. Por tanto, si la aplicación mantiene el estado, debe eliminar con cuidado el estado asociado con la conversación después de finalizar la conversación con un error.
Si un servicio no puede procesar un mensaje, significa que el servicio no puede finalizar la tarea de la conversación. Al finalizar la conversación con un error se notifica al otro participante de la conversación que la tarea ha generado un error.
Vea también
Conceptos
Otros recursos
RECEIVE (Transact-SQL)
END CONVERSATION (Transact-SQL)