Service Broker でアクティブ化タスクを制限しようとすると、Max_Queue_Readers プロパティは無視されます

この記事は、 プロパティによって設定された制限よりも多くのアクティブ化タスクが Service Broker で実行されたときに発生する問題を Max_Queue_Readers 解決するのに役立ちます。

元の製品バージョン: SQL Server 2017、SQL Server 2016、SQL Server 2014、SQL Server 2012、SQL Server 2008 R2
元の KB 番号: 3163368

現象

次のような状況で問題が発生します。

  • Windows、Microsoft SQL Server 2014、または SQL Server 2012 では、SQL Server 2017 で Service Broker を使用します。

  • 非同期ストアド プロシージャの実行に Service Broker を設定します。

  • アクティブ化ストアド プロシージャを Max_Queue_Readers 同時に実行するインスタンスの数を制限するには、Service Broker キューのプロパティを特定の値に設定します。

このシナリオでは、 に設定 Max_Queue_Readersされている値よりもアクティブ化されたタスクが実行されていることがわかります。

原因

この問題は、Service Broker データベースをシングル ユーザー モード () からマルチユーザー モード (RESTRICTED_USERMULTI_USER) に切り替える場合に、次を実行して発生する可能性があります。

ALTER DATABASE <dbname> SET MULTI_USER

データベースでユーザー モードが変更されると、Service Broker がシャットダウンされ、再起動されます。 このプロセス中に、既存 QueueMonitor のオブジェクトが削除され、オブジェクトの別の QueueMonitor インスタンスが作成されます。 Service Broker のシャットダウン中にアクティブ化プロセスが長時間の操作を実行している場合、オブジェクトの QueueMonitor 状態は削除に変更 されます

ただし、参照カウントが 0 に達していないため、既存 QueueMonitor のオブジェクト インスタンスは削除されません。 Service Broker の再起動時にアクティブ化プロシージャがまだ実行されている場合は、オブジェクトの QueueMonitor 新しいインスタンスとドロップされた QueueMonitor オブジェクトが同じキューに共存します。 ドロップされた QueueMonitor オブジェクト インスタンスは、Service Broker が次回起動すると削除されます。

回避策

この問題を回避するには、アクティブ化されたプロシージャが実行されていないときに実行 ALTER DATABASE <dbname> SET MULTI_USER してください。 これを行うには、次のいずれかの方法を使用します。

  • ユーザー モードを変更する前に、データベース内のすべてのキューを無効にしてから、すべてのキューを再度有効にします。

  • ユーザー モードを変更する前に、次のコマンドを実行して、影響を受けるすべてのキューのアクティブ化手順を無効にしてから、アクティブ化手順を再度有効にします。

    ALTER QUEUE <queueName> WITH ACTIVATION (STATUS = OFF)
    

詳細

次のようにクエリを実行することで、特定のキューに対して実行されているアクティブ化プロシージャの数をsys.dm_broker_activated_tasksチェックできます。

SELECT * FROM sys.dm_broker_activated_tasks WHERE queue_id = <queue number>

次のクエリを実行して、キュー モニターの状態を照会できます。

SELECT * FROM sys.dm_broker_queue_monitors WHERE queue_id = <queue number>

データベース・ユーザー・モードが変更された場合、キュー・モニターの状態は ドロップ として表示されます。