Sql server SQL Server Service Broker队列对话对话框

Sql server SQL Server Service Broker队列对话对话框,sql-server,service-broker,Sql Server,Service Broker,我和ServiceBroker合作了几个星期,在追踪一次对话时,我发现了一些奇怪的事情。。。对话结尾的队列中似乎有一条额外的消息,这也会导致错误发生 据我所知,对话对话框应如下所示: 触发火灾和呼叫开始对话 启动器服务将消息放置在队列上 目标服务触发存储的进程,接收消息并结束对话 启动器服务触发存储的进程,接收消息,并结束对话。 发生的情况是,队列末尾有一条额外的消息再次触发存储的进程,但详细信息(即会话句柄)为空。它还抛出一个错误:从字符串转换为uniqueidentifier时转换失败。为了

我和ServiceBroker合作了几个星期,在追踪一次对话时,我发现了一些奇怪的事情。。。对话结尾的队列中似乎有一条额外的消息,这也会导致错误发生

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

触发火灾和呼叫开始对话 启动器服务将消息放置在队列上 目标服务触发存储的进程,接收消息并结束对话 启动器服务触发存储的进程,接收消息,并结束对话。 发生的情况是,队列末尾有一条额外的消息再次触发存储的进程,但详细信息(即会话句柄)为空。它还抛出一个错误:从字符串转换为uniqueidentifier时转换失败。为了避免这个错误,我将会话句柄转换为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

没有任何额外的信息。只是在一个空队列上激活了您的过程。您激活的过程代码应该期望被激活并接收,以便不时返回一个空行集。如果您每次仅使用一条消息进行测试,则每次都会发生,正如您所观察到的,在实际负载下很少发生


在您的代码中,这种情况下接收空结果集将反映在NULL@handle、NULL@messageType和NULL@responseXML中,这与您描述的非常相似。

您的恶意消息的消息类型是什么?