开发者

How to quickly shut down all elements of Microsoft SQL Server Service Broker?

开发者 https://www.devze.com 2023-03-25 20:34 出处:网络
We have an app that creates queues and services in SQL Server using the Service Broker to handle db communication. The app uses these services and sends/receives messages correctly, but I now want to

We have an app that creates queues and services in SQL Server using the Service Broker to handle db communication. The app uses these services and sends/receives messages correctly, but I now want to test this app's initialization phase (it creates the broker as well as the stored procs that work behind the scenes). Basically, I need to drop the broker elements with some frequency, and its really really slow right now.

I am able to alter the way the app creates the broker elements if that helps - but this question is more related to shutting everything down.

The code I'm using to shut down the broker is:

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...

This hangs for some time on 'drop service [//XF/DBNotifyService-Initiator]'. Is there a quicker way to close and drop all or some elements of the service broker?

Thanks!

==Update==

Ok, it took me some time, but the answer below did solve the problem. I wanted to clarify for anyone else that might be having the issue.

My app correctly shut down all the services, queues, contracts, and messages. It was taking forever to shut down the services because there were a bunch of open conversations from a bug in the app. These conversations were being created, used to send a message, and then closed with:

END CONVERSATION @conversation with cleanup

The 'with cleanup' bit closes just the local end of the conversation (think, it allows the server to cleanup any conversations that might have errored out on the other end). It does not close the other end on the sending service, so conversations were being left open. Normal conversations should be ended:

END CONVERSATION @conversation

That fixed the app bug. However, I had several million broken conversations in the db. I could drop the db like a normal person, or I could try to figure out how to close them. To close them all one by one required:

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

That takes a few ms per connection (very slow for millions). If I wanted to close them all very quickly, use the answer below and run the modified开发者_如何转开发 command:

ALTER DATABASE [" + target.getTargetDbName() + "] SET NEW_BROKER WITH ROLLBACK IMMEDIATE;

The with rollback immediate makes all the connections drop without allowing them to ensure a commit. The documentation says 'All incomplete transactions will be rolled back and any other connections to the AdventureWorks2008R2 sample database will be immediately disconnected.' http://msdn.microsoft.com/en-us/library/bb522682.aspx

The services are dropping very quickly now, with the bug and the open connections gone.


The reason is slow is likely because those elements are locked with a SCH-S lock because they are in use, thus preventing your drop statements. The typical culprit is activated procedures that are running in the background. This can be quickly investigated by checking the Activity Monitor blocking reason(s) or by looking in sys.dm_exec_requests. Running activated procedures can be seen in sys.dm_broker_activated_tasks.

As a workaround you could try ALTER DATABASE SET NEW_BROKER, it will drop all existing conversations, but not queue/services/contracts/message types. It will also change the current database service_broker_instance_id (important if you used it in routes). By dropping all conversations the activated procedures should shutdown themselves (if they are correctly written).

But I would recommend a different approach. Rather than have your test reuse the same database again and again and handle all the false failures from the 'shutdown' phase, you should always start from a clean db and run your deployment script on a clean db. This way you do not need the 'removal' code. See Version Control and your Database. Us a database backup of a clean DB and always start from that, restore it and deploy your app, then run your validation tests.

0

精彩评论

暂无评论...
验证码 换一张
取 消

关注公众号