Sch-M WAIT блокує Sch-S у SQL Server 2014, але не SQL Server 2008 R2?


11

Нещодавно ми перенесли виробничі екземпляри з SQL 2008 R2 на абсолютно нові сервери SQL 2014. Ось цікавий сценарій, який ми розкрили за допомогою сервісного брокера. Розглянемо базу даних Broker Enabled = trueз MyServiceі MyQueue. Обробка повідомлень про отруєння відключена в цій черзі. У черзі є щонайменше 2 активних бесіди з повідомленнями.

В одному процесі (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) виконуйте п'ять разів :

BEGIN TRANSACTION;
DECLARE @conversation_group_id UNIQUEIDENTIFIER;
RECEIVE TOP (1) @conversation_group_id = conversation_handle FROM MyQueue;
ROLLBACK TRANSACTION;

Ключовим тут є те, що ми повертаємо транзакцію п'ять разів . Це запускає вбудовану фонову логіку Poison Message Handling . Хоча чергу не відключається (оскільки вона налаштована не відключати), фонове завдання все ще намагається виконати роботу та запустити broker_queue_disabledподію. Отже, якщо ми sys.dm_tran_locksзнову запитаємо, ми побачимо інший SPID (пов'язаний з BRKR TASK), який очікує на замок Sch-M.

| 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 та МС?
Макс Вернон

1
@MaxVernon ми працюємо 12.00.2370
Джозеф

3
Ви використовуєте ту саму послугу, що ініціатор та ціль Ці SENDблоки при перевірці ініціатора черзі. SENDне блокується на цільовій черзі, вона просто відскакує та використає sys.transmission_queueдля доставки. Якщо ви розділите ці два (завжди хороша ідея), у вас не виникне проблеми.
Ремус Русану

1
Дякую @RemusRusanu. Хоча цей приклад частково налаштований на демонстрацію змінити поведінку, ми пам’ятаємо про те, що ми розробляємо наші сервіси та черги.
Джозеф Дайґле

Відповіді:


17

Поведінка змінилася між SQL Server 2008 R2 та SQL Server 2012. Реалізація R2 2008 не відповідала задокументованій семантиці «розслабленої 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.

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.