3

Service Broker を使用して SQL Server でキューとサービスを作成し、db 通信を処理するアプリがあります。アプリはこれらのサービスを使用し、メッセージを正しく送受信しますが、このアプリの初期化フェーズをテストしたいと思います (ブローカーと、舞台裏で動作するストアド プロシージャを作成します)。基本的に、ブローカ要素をある程度の頻度で削除する必要がありますが、現在は非常に遅いです。

それが役立つ場合、アプリがブローカー要素を作成する方法を変更できますが、この質問はすべてをシャットダウンすることに関連しています。

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

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-Initiator]」でしばらくハングします。Service Broker のすべてまたは一部の要素を閉じて削除するより迅速な方法はありますか?

ありがとう!

==アップデート==

わかりました、少し時間がかかりましたが、以下の答えで問題は解決しました。問題を抱えている可能性のある他の人のために明確にしたかったのです。

私のアプリは、すべてのサービス、キュー、コントラクト、およびメッセージを正しくシャットダウンしました。アプリのバグによる未解決の会話がたくさんあったため、サービスをシャットダウンするのに非常に時間がかかりました。これらの会話は作成され、メッセージの送信に使用され、次のように閉じられました。

END CONVERSATION @conversation with cleanup

「with cleanup」ビットは、会話のローカル エンドのみを閉じます (これにより、サーバーは相手側でエラーになった可能性のある会話をクリーンアップできると考えてください)。送信サービスの相手側を閉じないため、会話は開いたままになっていました。通常の会話は終了する必要があります。

END CONVERSATION @conversation

これにより、アプリのバグが修正されました。ただし、データベースには数百万の壊れた会話がありました。通常の人のようにデータベースをドロップするか、それらを閉じる方法を見つけようとすることができます。それらをすべて 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;

with rollback immediate は、コミットを保証することなく、すべての接続をドロップします。ドキュメントには、「すべての不完全なトランザクションはロールバックされ、AdventureWorks2008R2 サンプル データベースへのその他の接続は直ちに切断される」と記載されています。 http://msdn.microsoft.com/en-us/library/bb522682.aspx

バグと開いている接続がなくなったため、サービスは現在非常に急速に低下しています。

4

1 に答える 1

6

遅い理由は、これらの要素が使用されているために SCH-S ロックでロックされているため、drop ステートメントが妨げられている可能性があります。典型的な原因は、バックグラウンドで実行されているアクティブ化されたプロシージャです。これは、 Activity Monitorのブロック理由を確認するか、 を調べることで、すぐに調査できますsys.dm_exec_requests。アクティブ化されたプロシージャの実行は、 で確認できますsys.dm_broker_activated_tasks

試すことができる回避策として、ALTER DATABASE SET NEW_BROKER既存のすべての会話をドロップしますが、キュー/サービス/コントラクト/メッセージ タイプはドロップしません。また、現在のデータベースも変更されますservice_broker_instance_id(ルートで使用した場合は重要です)。すべての会話をドロップすることにより、アクティブ化されたプロシージャーはそれ自体をシャットダウンする必要があります (正しく記述されている場合)。

しかし、私は別のアプローチをお勧めします。テストで同じデータベースを何度も再利用して、「シャットダウン」フェーズからのすべての誤った失敗を処理するのではなく、常にクリーンなデータベースから開始し、クリーンなデータベースでデプロイ スクリプトを実行する必要があります。この方法では、「削除」コードは必要ありません。バージョン管理とデータベースを参照してください。クリーンな DB のデータベース バックアップを使用し、常にそこから開始し、それを復元してアプリをデプロイしてから、検証テストを実行します。

于 2011-08-03T18:23:17.530 に答える