代码之家  ›  专栏  ›  技术社区  ›  roryok

Service Broker:与清理一起使用时,Sys.Conversation_终结点将填充CO/转换消息

  •  3
  • roryok  · 技术社区  · 14 年前

    我们最近发现一个数据库有问题,由于“fire&forget”设置(即:发送后立即关闭会话),sys.conversation_endpoints表中的入站消息已被di/disconnected_填满。这最终会溢出到tempdb中,导致它大幅度增长并耗尽宝贵的磁盘空间。我们最终通过评论来解决这个问题

    END CONVERSATION @handle WITH CLEANUP

    在发送SP和使用相同代码关闭接收SP中的对话时,

    结束会话@handle并清除

    然而,我们现在有一个新问题。自从移动服务器(以及从SQL Server 2005迁移到SQL Server 2008)以来,我们最近发现sys.conversation_终结点现在正在填充co/conversation消息,这表明会话没有关闭。接收SP正在关闭它们,或者至少正在运行这样做的命令,所以我不知道这些消息从何而来。

    我试着回到发送点结束对话,但没有效果。在接收端使用 WITH CLEANUP ? 还是有其他问题?

    这个 post on techtarget 似乎暗示这是一个错误,运行一个工作来清理剩余的是唯一的解决方案。。。

    更新: pawel在下面指出,我应该避免fire&forget模式,我已经向发起程序队列添加了一个激活的sp来结束任何对话。但是,sys.conversation_端点仍在填满,这次是CD/关闭的消息这是我的队列结构

    发送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)
    

    接收SP(目标队列上已激活的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;
    

    结束SP(启动队列上已激活的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 回复  |  直到 14 年前
        1
  •  1
  •   Pawel Marciniak    14 年前

    使用fire and forget模式将不可避免地导致这类问题和其他类型的问题。此外,它会使任何假设的错误不被注意。是否有任何原因不能更改消息交换模式以使目标发出结束对话(不清除!)一旦它接收到一条消息,然后发起程序只在从目标接收到结束会话消息时调用结束会话(再次调用,不清除)?