【问题标题】:SQL Server Service Broker Queue conversation dialogSQL Server Service Broker 队列对话对话框
【发布时间】:2012-08-01 01:10:17
【问题描述】:

我已经与 Service Broker 合作了几个星期,在跟踪对话时,我发现了一些奇怪的东西......对话的最后似乎有一条额外的消息在队列中,这也会导致错误发生。

据我了解,对话对话框应如下所示:

  1. 触发火灾和呼叫开始对话
  2. 发起者服务将消息放入队列
  3. 目标服务触发存储过程,接收消息并结束对话
  4. Initiator 服务触发存储过程,接收消息并结束对话。

发生的情况是队列末尾有一条额外的消息再次触发存储的过程,但详细信息(即会话句柄)为空。它还会引发错误:Conversion failed when converting from a character string to uniqueidentifier. 为了解决该错误,我将 conversation_handle 转换为 varchar,然后检查 null。对我来说似乎很愚蠢,我必须这样做。

更新:错误已经消失 - 我相信它是在我尝试记录会话句柄(为空)时发生的。

结束对话而不收到额外消息的正确方法是什么?

这是我现在拥有的:

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

【问题讨论】:

  • 您的“流氓”消息的消息类型是什么?

标签: sql-server service-broker


【解决方案1】:

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

在您的代码中,这种情况(接收空结果集)将反映为 NULL @handle、NULL @messageType 和 NULL @responseXML,这与您所描述的差不多。

【讨论】:

    猜你喜欢
    • 2010-11-21
    • 2013-09-07
    • 1970-01-01
    • 2010-11-18
    • 2011-02-18
    • 2014-11-14
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多