我们有一个应用程序,它使用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]'上挂起一段时间。有没有更快捷的方法来关闭和删除服务代理的所有或部分元素?
谢谢!
==更新==
好的,我花了一些时间,但下面的答案确实解决了这个问题。我想澄清可能遇到这个问题的其他任何人。
我的应用正确关闭了所有服务,队列,合同和消息。关闭服务需要花费很长时间,因为应用程序中的一个bug会有一堆开放的对话。正在创建这些对话,用于发送消息,然后以:
关闭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
现在服务正在迅速下降,错误和开放连接已经消失。
答案 0 :(得分:5)
原因很慢可能是因为这些元素被SCH-S锁定锁定,因为它们正在使用中,从而阻止了drop语句。典型的罪魁祸首是在后台运行的激活程序。通过查看Activity Monitor阻止原因或查看sys.dm_exec_requests
,可以快速调查此问题。在sys.dm_broker_activated_tasks
中可以看到运行激活的程序。
作为一种解决方法,您可以尝试ALTER DATABASE SET NEW_BROKER
,它将删除所有现有会话,但不会删除队列/服务/合同/消息类型。它还将更改当前数据库service_broker_instance_id
(如果您在路由中使用它,则很重要)。通过删除所有会话,激活的过程应该自行关闭(如果它们被正确写入)。
但我会推荐一种不同的方法。您应该始终从干净的数据库启动并在干净的数据库上运行部署脚本,而不是让您的测试一次又一次地重复使用同一个数据库并处理所有错误的故障。这样您就不需要“删除”代码。见Version Control and your Database。我们是一个干净数据库的数据库备份,并始终从那里开始,恢复它并部署您的应用程序,然后运行您的验证测试。