Service Broker:使用 With Cleanup 时 Sys.Conversation_endpoints 会填充 CO/CONVERSING 消息
我们最近发现我们的一个数据库存在问题,该问题是由于“火灾和火灾”导致的。忘记'设置(即:发送后立即关闭对话),我们的 sys.conversation_endpoints 表被 DI/DISCONNECTED_INBOUND 消息填满。这最终会溢出到 tempDB 中,导致它急剧增长并耗尽宝贵的磁盘空间。我们最终解决了这个问题,方法是在发送 SP 中注释掉行
END CONVERSATION @handle WITH CLEANUP
关闭接收 SP 中的对话
,并使用相同的代码END CONVERSATION @handle WITH CLEANUP< < /code>
然而,我们现在遇到了一个新问题。自从移动服务器(并从 SQL Server 2005 迁移到 SQL Server 2008)以来,我们最近发现 sys.conversation_endpoints 现在充满了 CO/CONVERSING 消息,表明对话尚未关闭。接收 SP 正在关闭它们,或者至少正在运行命令来这样做,所以我不明白这些消息来自哪里。
我尝试返回到发送时结束对话,但没有效果。使用 WITH CLEANUP
在接收端结束对话是否错误?或者还有其他问题吗?
此techtarget 上的帖子 似乎表明它是一个错误,运行作业来清理剩余物是唯一的解决方案......
更新: 帕维尔在下面指出,我应该避免火灾和火灾。忘记模式,我已将激活的 SP 添加到发起者队列中以结束任何对话。然而,sys.conversation_endpoints 仍然填满,这次是 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;
We recently identified a problem with one of our databases where as a result of a 'fire & forget' setup (i.e: conversations being closed immediately after sending), our sys.conversation_endpoints table was filling up with DI/DISCONNECTED_INBOUND messages. This eventually spilled over into the tempDB, causing it to grow enormously and eat up precious disk space. We eventually resolved this issue by commenting out the line
END CONVERSATION @handle WITH CLEANUP
in our sending SP and closing the conversations in our receiving SP using the same code,
END CONVERSATION @handle WITH CLEANUP
However, we now have a new issue. Since moving servers (and migrating from SQL Server 2005 to SQL Server 2008) we've recently discovered that sys.conversation_endpoints is now filling up with CO/CONVERSING messages, indicating that the conversations are not being closed. The receiving SP is closing them, or at least is running the command to do so, so I don't understand where these messages are coming from.
I've tried going back to ending the conversation at the point of send, but it has no effect. Is it wrong to end conversations on the receiving end using WITH CLEANUP
? Or is there some other problem?
This post on techtarget seems to suggest its a bug, and that running a job to cleanup the leftovers is the only solution...
UPDATE:
Pawel pointed out below that I should be avoiding the Fire & Forget Pattern, and I've added an activated SP to the initiator queue to end any conversations. However, sys.conversation_endpoints is STILL filling up, this time with CD/CLOSED messages. Here's the structure of my queues
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 (Activated SP on TargetQueue)
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 (Activated SP on InitiatorQueue)
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;
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
使用“即发即忘”模式将不可避免地导致此类问题和其他类型的问题。此外,它将使任何假设的错误都不会被注意到。是否有任何原因无法更改消息交换模式,以便目标在收到消息后发出 END CONVERSATION (无需清理!),然后发起者仅在收到结束对话消息时调用 END CONVERSATION (再次,无需清理)从目标?
Using the fire-and-forget pattern will inevitably lead to this and other types of issues. Additionally it will make any hypothetical errors go unnoticed. Is there any reason why you can't change the message exchange pattern so that the target issues END CONVERSATION (without cleanup!) once it receives a message and then the initiator only calls END CONVERSATION (again, without cleanup) upon receiving end conversation message from the target?