Sql server Service Broker:Sys.Conversation_端点在与Cleanup一起使用时填充CO/转换消息

Sql server Service Broker:Sys.Conversation_端点在与Cleanup一起使用时填充CO/转换消息,sql-server,sql-server-2008,service,service-broker,Sql Server,Sql Server 2008,Service,Service Broker,最近,我们发现我们的一个数据库存在一个问题,由于“启动并忘记”设置(即:发送后立即关闭对话),我们的sys.conversation_endpoints表中充满了DI/DISCONNECTED_入站消息。这最终会溢出到tempDB中,导致它大量增长并占用宝贵的磁盘空间。我们最终通过注释这一行解决了这个问题 END CONVERSATION@handle WITH CLEANUP 在发送SP中,使用相同的代码关闭接收SP中的对话 END CONVERSATION@handle WITH CLEAN

最近,我们发现我们的一个数据库存在一个问题,由于“启动并忘记”设置(即:发送后立即关闭对话),我们的sys.conversation_endpoints表中充满了DI/DISCONNECTED_入站消息。这最终会溢出到tempDB中,导致它大量增长并占用宝贵的磁盘空间。我们最终通过注释这一行解决了这个问题

END CONVERSATION@handle WITH CLEANUP

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

END CONVERSATION@handle WITH CLEANUP

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

我试着在发送时结束对话,但没有效果。使用带有清理功能的
在接收端结束对话是否错误?还是有其他问题

这似乎表明这是一个bug,运行一个作业来清理剩菜是唯一的解决方案

更新: Pawel在下面指出,我应该避免使用Fire&Forget模式,并且我已经在启动器队列中添加了一个激活的SP来结束任何对话。但是,sys.conversation_端点仍在填充,这一次是CD/CLOSED消息。这是我的队列结构

发送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(TargetQueue上激活的SP)

结束SP(启动器队列上已激活的SP)


使用fire-and-forget模式将不可避免地导致这类和其他类型的问题。此外,它将使任何假设的错误不被注意。您有什么原因不能更改消息交换模式,使目标在收到消息后发出结束会话(无清除!),然后启动器仅在收到目标的结束会话消息时调用结束会话(同样,无清除)?

Hi Pawel,我当然可以用我一直使用的清洁剂来清除,你认为这会造成问题吗?我知道我使用的模式不是最好的,但它适合我们的服务类型。当你说fire and forget模式适合你的服务类型时,你含蓄地承认fire and forget的固有问题也适合服务类型。换言之,你是说你对会话端点的填充、丢失的消息和错过的错误没有意见。我个人不认为任何类型的服务(至少不是我想使用的任何服务)都可以解决这些问题,这就是为什么我建议采用“放下火,忘记一切”的方法。但是最后当然是你的选择了。嗨,波维尔,我不完全明白。我们目前有一个系统,它通过ServiceBroker队列从asp.net应用程序向数据库发送单向消息。接收激活过程使用一个表变量,一次从队列中提取1000条消息,处理并结束每一条消息。因此,消息可以在队列中停留几秒钟。我假设(可能是错误的)将启动器更改为同时侦听这些消息的结束对话会给系统带来严重的延迟(即每次请求几秒钟),这是否不准确?我刚刚意识到我也可以在启动器队列上放置一个激活的sp,这当然会消除任何延迟问题。Doh。不幸的是,它仍然不起作用-我现在正在更新问题目标端的对话端点应该在对话结束后(在关闭状态下)保留一段时间。这是一种安全措施,是设计的。然而,他们应该在大约30分钟后离开。这就是你看到的吗?
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;
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;