Sch-M WAITはSQL Server 2014でSch-Sをブロックしますが、SQL Server 2008 R2ではブロックしませんか?


11

最近、実稼働インスタンスをSQL 2008 R2から新しいSQL 2014サーバーに移行しました。Service Brokerの使用法で明らかになった興味深いシナリオを次に示します。でデータベースを考えてみましょうBroker Enabled = trueMyServiceして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でロック動作は変更されましたか?このロック動作に影響を与える可能性のあるデータベースまたはサーバー設定はありますか?


バグのようです。最新のSPとCUを適用しましたか?
Max Vernon

1
@MaxVernonは12.00.2370を実行しています
Joseph Daigle

3
イニシエーターおよびターゲットと同じサービスを使用しています。SENDブロック確認しながら、開始剤のキューを。ターゲットキューでSENDブロックするのではなく、単にバウンスして配信に使用します。2つを分離すると(常に良いアイデアです)、問題は発生しません。sys.transmission_queue
Remus Rusanu 2014

1
@RemusRusanuに感謝します。この例は、変更された動作を示すために部分的に工夫されていますが、サービスとキューを設計するときに覚えておくべきヒントはあなたのものです。
ジョセフデイグル2014

回答:


17

SQL Server 2008 R2とSQL Server 2012の間で動作が変更されました。2008R2の実装は、文書化された「リラックスしたFIFO」のセマンティクスと一致していませんでした。

ロックは、リラックスした先入れ先出し(FIFO)方式で許可されます。順序は厳密なFIFOではありませんが、飢餓の回避などの望ましい特性を保持し、不要なデッドロックとブロッキングを減らすように機能します。

リクエスターがまだリソースのロックを所有していない新しいロック要求は、要求されたモードが許可された要求の結合と保留中の要求のモードと互換性がない場合にブロックされます。

変換要求がブロックされるのは、要求されたモードが、変換要求自体が最初に付与されたモードを除いて、付与されたすべてのモードの和集合と互換性がない場合のみです。

2008 R2では、Sch-S許可された要求と待機中の要求の結合との互換性がないにもかかわらず、新しいロック要求が許可され、ロックの枯渇につながる可能性があります。2012年、Sch-Sロックリクエストはブロックされます。

以下の再現スクリプトでは、Service Brokerキューではなく通常のテーブルを使用しています。

-- Session 1
CREATE TABLE dbo.LockTest (col1 integer NULL);

INSERT dbo.LockTest (col1) VALUES (1);

BEGIN TRANSACTION;

-- Will hold row-X, Pag-IX, and Tab-IX
INSERT dbo.LockTest (col1) VALUES (2);

-- Session 2
-- Blocked waiting on Sch-M
TRUNCATE TABLE dbo.LockTest;

-- Session 3
-- Takes Sch-S only
-- Not blocked in 2008 R2
SELECT * FROM dbo.LockTest AS LT WITH (READUNCOMMITTED);

要約すると、2008 R2は設計どおりに動作しませんでした。この問題はSQL Server 2012で修正されました。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.