我们有一个应用程序,它使用 Service Broker 在 SQL Server 中创建队列和服务来处理数据库通信。该应用程序使用这些服务并正确发送/接收消息,但我现在想测试这个应用程序的初始化阶段(它创建代理以及在幕后工作的存储过程)。基本上,我需要以某种频率删除代理元素,而且它现在真的很慢。
如果有帮助,我可以更改应用程序创建代理元素的方式 - 但这个问题与关闭所有内容更相关。
我用来关闭代理的代码是:
receive * from [dbo].[notify_initiator_queue]
alter queue [dbo].[notify_initiator_queue] with status = OFF
drop service [//DBNotifyService-Initiator]
drop queue [dbo].[notify_initiator_queue]
drop message types, contacts, etc...
这会在“drop service [//XF/DBNotifyService-Initiator]”上挂起一段时间。是否有更快的方法来关闭和删除服务代理的全部或部分元素?
谢谢!
==更新==
好的,我花了一些时间,但下面的答案确实解决了问题。我想为其他可能遇到问题的人澄清一下。
我的应用程序正确关闭了所有服务、队列、合同和消息。关闭服务需要很长时间,因为应用程序中的一个错误有一堆开放的对话。正在创建这些对话,用于发送消息,然后以以下方式结束:
END CONVERSATION @conversation with cleanup
'with cleanup' 位仅关闭对话的本地端(想想,它允许服务器清理任何可能在另一端出错的对话)。它不会关闭发送服务的另一端,因此对话保持打开状态。正常对话应该结束:
END CONVERSATION @conversation
这修复了应用程序错误。但是,我在数据库中有几百万次中断的对话。我可以像普通人一样删除数据库,或者我可以尝试弄清楚如何关闭它们。要一一关闭它们:
declare @conversation uniqueidentifier
while exists (select top 1 conversation_handle from sys.transmission_queue )
begin
set @conversation = (select top 1 conversation_handle from sys.transmission_queue )
end conversation @conversation with cleanup
end
每个连接需要几毫秒(对于数百万来说非常慢)。如果我想快速关闭它们,请使用下面的答案并运行修改后的命令:
ALTER DATABASE [" + target.getTargetDbName() + "] SET NEW_BROKER WITH ROLLBACK IMMEDIATE;
with rollback immediate 使所有连接都断开,而不允许它们确保提交。文档说“所有未完成的事务都将被回滚,并且与 AdventureWorks2008R2 示例数据库的任何其他连接都将立即断开。” http://msdn.microsoft.com/en-us/library/bb522682.aspx
这些服务现在正在迅速下降,错误和打开的连接都消失了。