SQL Server Service Broker队列对话对话框

时间:2012-08-03 01:21:35

标签: sql-server service-broker

我几周来一直在与Service Broker合作,在跟踪对话时,我发现了一些奇怪的事情......对话似乎在队列中有一条额外的消息,这也会导致错误发生。< / p>

根据我的理解,对话对话框应如下所示:

  1. 触发器触发并呼叫开始对话
  2. 发起人服务将消息放在队列
  3. 目标服务触发存储过程,接收消息并结束对话
  4. 启动器服务触发存储过程,接收消息并结束对话。
  5. 正在发生的事情是队列中有一条额外的消息,它会再次触发存储过程,但细节(即conversation_handle)为空。它还会抛出一个错误:Conversion failed when converting from a character string to uniqueidentifier.为了解决错误,我将conversation_handle转换为varchar,然后检查null。对我来说似乎很愚蠢,我必须这样做。

    更新: 错误已经消失 - 我相信当我尝试记录conversation_handle(无效)时会发生错误。

    在没有收到额外消息的情况下结束对话的正确方法是什么?

    这就是我现在所拥有的:

    alter proc dbo.MessageProcessor
    as
    
    begin
    
        set nocount on;
        set xact_abort on;
    
        declare @xactState smallint
    
        declare @handle uniqueidentifier, 
                @responseXml xml, 
                @messageType sysname;
    
        begin transaction;
        begin try
    
            ;receive top(1)
                @messageType = message_type_name, 
                @handle = conversation_handle, 
                @responseXml = message_body
            from dbo.MessageQueue
    
            if(@handle is not null)
            begin
    
                if (@messageType = N'DEFAULT')
                begin
    
                    save transaction MessageProcessor_Tran
    
                    begin try
    
                        -- doing work here
    
                    end try
                    begin catch
    
                        select @xactState = xact_state()
    
                        if(@xactState = -1)
                        begin
                            rollback;
                            raiserror(N'Unrecoverable error', 16, 1)
                        end
                        else if(@xactState = 1)
                        begin
                            rollback transaction MessageProcessor_tran
                        end
    
                        -- log error information
    
                    end catch
                end 
                else if (@messageType = N'http://schemas.microsoft.com/SQL/ServiceBroker/Error')
                begin
                    declare @errorNumber int,
                            @errorMessage nvarchar(4000);
    
                    with xmlnamespaces (DEFAULT N'http://schemas.microsoft.com/SQL/ServiceBroker/Error')
                    select @errorNumber = @responseXml.value ('(/Error/Code)[1]', 'INT'),
                        @errorMessage = @responseXml.value ('(/Error/Description)[1]', 'NVARCHAR(4000)');
                    -- log error
                end
    
                end conversation @handle
                set @handle = null
            end
    
            commit
        end try
    
        begin catch
    
            declare @error int, 
                    @message nvarchar(2048)
    
            select @error = error_number(), 
                @message = error_message(), 
                @xactState = xact_state();
    
            if(@xactState <> 0)
                rollback;
    
            if(@handle is not null)
                end conversation @handle;
    
            -- log error            
            raiserror(N'Error: %i, %s', 1, 60, @error, @message) with log;
    
        end catch
    end
    go
    

1 个答案:

答案 0 :(得分:2)

不是任何额外的消息。只是在空队列中激活了您的过程。你的激活程序代码应该被激活,并且RECEIVE会不时地返回一个空的行集(如果你一次只用一条消息来测试它,那么每次都会发生这种情况,正如你所观察到的,在实际负载下它很少会发生) 。

在你的代码中,这样的情况(RECEIVE空结果集)将反映在NULL @ handle,NULL @messageType和NULL @responseXML中,这几乎就是你所描述的。