最近、実稼働インスタンスをSQL 2008 R2から新しいSQL 2014サーバーに移行しました。Service Brokerの使用法で明らかになった興味深いシナリオを次に示します。でデータベースを考えてみましょうBroker Enabled = true
とMyService
してMyQueue
。このキューでは、有害メッセージの処理が無効になっています。キューにメッセージがあるアクティブな会話が2つ以上あります。
1つのプロセス(SPID 100)で実行します。
BEGIN TRANSACTION;
DECLARE @conversation_group_id UNIQUEIDENTIFIER;
RECEIVE TOP (1) @conversation_group_id = conversation_handle FROM MyQueue;
トランザクションは開いたままにしていることに注意してください。これは、外部リソースで長時間待機している.NETプログラムであると想像してください。経てsys.dm_tran_locks
、私たちは、このSPIDがキューにIXロックが付与されていることがわかります。
| type | resource_id | mode | status | spid |
| OBJECT | 277576027 | IX | GRANT | 100 |
別のプロセス(SPID 101)で5回実行します。
BEGIN TRANSACTION;
DECLARE @conversation_group_id UNIQUEIDENTIFIER;
RECEIVE TOP (1) @conversation_group_id = conversation_handle FROM MyQueue;
ROLLBACK TRANSACTION;
ここで重要なのは、トランザクションを5回ロールバックすることです。これにより、組み込みの有害メッセージ処理のバックグラウンドロジックがトリガーされます。キューが無効にならない(無効にならないように構成されているため)間、バックグラウンドタスクは引き続き作業を行い、broker_queue_disabled
イベントを発生させようとしています。したがって、sys.dm_tran_locks
もう一度クエリを実行するとBRKR TASK
、Sch-Mロックを待機している(に関連付けられた)別のSPIDが表示されます。
| type | resource_id | mode | status | spid |
| OBJECT | 277576027 | IX | GRANT | 100 |
| OBJECT | 277576027 | Sch-M | WAIT | 36 |
これまでのところ、すべてが理にかなっています。
最後に、別のプロセス(SPID 102)で、そのキューを使用してサービスへの送信を試みます。
BEGIN TRANSACTION;
DECLARE @ch uniqueidentifier;
BEGIN DIALOG @ch FROM SERVICE [MyService] TO SERVICE 'MyService';
SEND ON CONVERSATION @ch ('HELLO WORLD');
SEND
コマンドがブロックされています。もう一度sys.dm_tran_locks
見ると、このプロセスがSch-Sロックを待機していることがわかります。実行sp_who2
すると、SPID 102がSPID 36によってブロックされていることがわかります。
| type | resource_id | mode | status | spid |
| OBJECT | 277576027 | IX | GRANT | 100 |
| OBJECT | 277576027 | Sch-M | WAIT | 36 |
| OBJECT | 277576027 | Sch-S | WAIT | 102 |
なぜSch-Sロックは、待機しているSch-Mロックを待機するのですか?
この動作はSQL 2008 R2では完全に異なります。このまったく同じシナリオを使用して、まだ廃止されていない 2008R2インスタンスで実行すると、SEND
コマンドを含む最終バッチは、待機中のSch-Mロックによってブロックされません。
SQL 2012または2014でロック動作は変更されましたか?このロック動作に影響を与える可能性のあるデータベースまたはサーバー設定はありますか?
SEND
ブロック確認しながら、開始剤のキューを。ターゲットキューでSEND
ブロックするのではなく、単にバウンスして配信に使用します。2つを分離すると(常に良いアイデアです)、問題は発生しません。sys.transmission_queue