我们最近发现我们的一个数据库存在问题,由于“触发后忘记”设置(即:发送后立即关闭对话),我们的 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
吗?还是有其他问题?
techtarget 上的这篇文章似乎暗示它是一个错误,并且运行清理剩余物的工作是唯一的解决方案......
更新:Pawel 在下面指出,我应该避免使用 Fire & Forget 模式,并且我已将激活的 SP 添加到发起程序队列以结束任何对话。但是,sys.conversation_endpoints 仍然被填满,这次是 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)
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;