Sch-M WAIT блокирует Sch-S в SQL Server 2014, но не SQL Server 2008 R2?

11

Недавно мы перенесли наши производственные экземпляры с SQL 2008 R2 на новые серверы SQL 2014. Вот интересный сценарий, который мы раскрыли при использовании Service Broker. Рассмотрим базу данных с 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;

Ключевым моментом здесь является то, что мы откатываем транзакцию пять раз . Это запускает встроенную фоновую логику обработки сообщений отравления . Хотя очередь не отключается (поскольку она настроена на отключение), фоновая задача все еще пытается выполнить работу и запустить 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 и CU?
Макс Вернон,
1
@MaxVernon, мы бежим 12.00.2370
Джозеф
3
Вы используете тот же сервис, что и инициатор и цель. Эти SENDблоки при проверке инициатора очереди. SENDне будет блокировать целевую очередь, он будет просто отказов и использовать sys.transmission_queueдля доставки. Если вы разделите два (всегда хорошая идея), у вас не будет проблемы.
Ремус Русану
1
Спасибо @RemusRusanu. Хотя этот пример частично придуман, чтобы продемонстрировать изменившееся поведение, мы будем учитывать ваш совет при разработке наших служб и очередей.
Джозеф Дейгл

Ответы:

17

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

Пол Уайт 9
источник