2011-08-03 7 views
2

DBコミュニケーションを処理するためにService Brokerを使用してSQL Serverにキューとサービスを作成するアプリケーションがあります。アプリはこれらのサービスを使用してメッセージを正しく送受信しますが、このアプリケーションの初期化フェーズ(ブローカとバックグラウンドで動作するストアドプロシージャを作成します)をテストします。基本的には、ブローカの要素をいくつかの頻度で削除する必要があります。Microsoft SQL Server Service Brokerのすべての要素をすばやくシャットダウンする方法はありますか。

私は、アプリケーションがブローカ要素を作成する方法を変更することができます。しかし、この問題はすべてをシャットダウンすることに関連しています。

私はブローカをシャットダウンするために使用しているコードは次のとおりです。

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

これは、「ドロップサービス[// XF/DBNotifyServiceイニシエータ]」にいくつかの時間のためにハングします。サービスブローカーのすべてまたは一部の要素を閉じて削除するためのより迅速な方法はありますか?

ありがとうございます!

==更新==

[OK]を、それは私にいくつかの時間がかかりましたが、以下の答えは、問題を解決しました。私はこの問題を抱えている可能性がある他の誰かを明確にしたかったのです。

私のアプリケーションは、すべてのサービス、キュー、契約、およびメッセージを正しくシャットダウンします。アプリのバグからのオープンな会話がたくさんあったので、サービスをシャットダウンすることは永遠に取っていた。これらの会話は、作成されたメッセージを送信するために使用し、その後で閉鎖されていた:

END CONVERSATION @conversation with cleanup 

「クリーンアップと」ビットは、会話のちょうどローカルエンドを閉じて(と思う、それはクリーンアップにサーバーを可能にする任意の会話は、もう一方の端でエラーが発生している可能性があります)。それは、送信サービスのもう一方の終わりを閉じないので、会話は開いたままです。通常の会話は終了する必要があります。

END CONVERSATION @conversation 

これでアプリのバグが修正されました。しかし、私は数百万の壊れた会話をデータベースに持っていました。私は普通の人のようにDBを落とすことができます、または私はそれらを閉じる方法を見つけることができます。すべてを1つずつ閉じるには、次の手順を実行します。

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; 

:私は非常に迅速にそれらをすべて閉じしたい場合は、修正されたコマンドを下の解答を使用して実行します。ドキュメントには、「不完全なトランザクションはすべてロールバックされ、AdventureWorks2008R2サンプルデータベースへの他の接続はただちに切断されます」と記載されています。 http://msdn.microsoft.com/en-us/library/bb522682.aspx

サービスは非常に速くなりました。バグとオープンな接続がなくなりました。

答えて

5

理由が遅いのは、それらの要素が使用中であるためにSCH-Sロックでロックされているために、ドロップステートメントが実行されないためです。典型的な原因は、バックグラウンドで実行されているアクティブ化されたプロシージャです。 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を参照してください。私たちはクリーンなデータベースのデータベースバックアップを作成し、常にそれを開始し、それを復元し、あなたのアプリを展開してから、検証テストを実行します。

+0

シャットダウンが正しく行われなかったキュースレッドがいくつかありましたので、開いている接続を処理する方法を見つけることができました。 dbバックアップごとに - 良いアイデアですが、専用のテスターだけでなく、どのデータベースでもテストを実行できるようにしたいと考えています。ありがとう。 – Noah

関連する問題