Service Broker:使用With Cleanup时,Sys.Conversation_endpoints会填充CO / CONVERSING消息

时间:2010-08-10 10:28:45

标签: sql-server sql-server-2008 service service-broker

我们最近发现了一个我们的数据库存在问题,其中包括“火灾”和“火灾”。忘记'设置(即:会话在发送后立即关闭),我们的sys.conversation_endpoints表填满了DI / DISCONNECTED_INBOUND消息。这最终蔓延到tempDB中,导致它大量增长并占用宝贵的磁盘空间。我们最终通过注释掉

行解决了这个问题

END CONVERSATION @handle WITH CLEANUP

在我们发送SP并使用相同代码关闭接收SP中的会话

END CONVERSATION @handle WITH CLEANUP

但是,我们现在有了一个新问题。自从移动服务器(以及从SQL Server 2005迁移到SQL Server 2008)以来,我们最近发现sys.conversation_endpoints现在正在填充CO / CONVERSING消息,表明对话没有被关闭。接收SP正在关闭它们,或者至少运行命令来执行此操作,因此我不明白这些消息来自何处。

我已经尝试在发送时回去结束对话,但它没有效果。使用WITH CLEANUP结束接收端的会话是错误的吗?还是有其他问题吗?

post on techtarget似乎表明它是一个错误,并且运行清理残羹剩饭的工作是唯一的解决方案......

更新: 帕维尔在下面指出,我应该避开Fire&忘记模式,我已经将激活的SP添加到启动器队列以结束任何对话。但是,sys.conversation_endpoints仍然是STILL填充,这次是CD / CLOSED消息。这是我队列的结构

Send_SP:

DECLARE @h UNIQUEIDENTIFIER 
BEGIN DIALOG CONVERSATION @h 
FROM SERVICE 'InitiatorQueue' TO SERVICE 'TargetQueue' 
ON CONTRACT 'MyContract' WITH ENCRYPTION = OFF; 
SEND ON CONVERSATION @h MESSAGE TYPE 'MyMessage' (@msg)

Receive_SP(在TargetQueue上激活SP)

DECLARE @type SYSNAME, @h UNIQUEIDENTIFIER, @msg XML;
DECLARE @target TABLE (
    [message_type_name] SYSNAME,
    [message_body] VARBINARY(MAX),
    [conversation_handle] UNIQUEIDENTIFIER
)
WHILE(1=1)
BEGIN TRANSACTION
    WAITFOR(RECEIVE TOP (1000) 
        [message_type_name],[message_body],[conversation_handle] 
        FROM TargetQueue INTO @target), TIMEOUT 2000            
    IF(@@rowcount!=0)
    BEGIN
        WHILE((SELECT count(*) FROM @target) > 0) 
        BEGIN
        SELECT TOP (1) @type = [message_type_name],
            @msg = [message_body],
            @h = [conversation_handle]  FROM @target;
        // Handle Message Here
        END CONVERSATION @h; 
        DELETE TOP (1) FROM @target;
    END
END
COMMIT TRANSACTION;

End_SP(在InitiatorQueue上激活SP)

DECLARE @type SYSNAME, @h UNIQUEIDENTIFIER, @msg XML;
DECLARE @init TABLE (
    [message_type_name] SYSNAME,
    [message_body] VARBINARY(MAX),
    [conversation_handle] UNIQUEIDENTIFIER
)
WHILE(1=1)
BEGIN TRANSACTION
    WAITFOR(RECEIVE TOP (1000) 
        [message_type_name],[message_body],[conversation_handle] 
        FROM InitiatorQueue INTO @init), TIMEOUT 2000           
    IF(@@rowcount!=0)
    BEGIN
        WHILE((SELECT count(*) FROM @init) > 0) 
        BEGIN
        SELECT TOP (1) @type = [message_type_name],
            @msg = [message_body],
            @h = [conversation_handle]  FROM @init;
        END CONVERSATION @h; 
        DELETE TOP (1) FROM @init;
    END
END
COMMIT TRANSACTION;

1 个答案:

答案 0 :(得分:1)

使用“即发即忘”模式将不可避免地导致此类和其他类型的问题。此外,它将使任何假设错误都不被注意。是否有任何理由不能更改消息交换模式,以便目标在收到消息后发出END CONVERSATION(无需清除!),然后发起者在接收到结束对话消息时仅调用END CONVERSATION(再次,不进行清理)从目标?