Skip to content

Хинты запроса, которые вы можете использовать, чтобы избежать блокировок

Пересказ статьи Brent Ozar. Query Hints You Can Use to Avoid Blocking


Нет, это не NOLOCK. Тут вы получаете неверные результаты запроса, даже когда результаты вашего запроса не подвергаются изменениям.
Я говорю о случае, когда вам нужно выполнить запись, но вы хотите, чтобы ваш запрос работал наряду с другими в средах с высоким уровнем параллелизма, не создавая блокировочного шторма.

SET LOCK_TIMEOUT 1000 - если вы выполните это перед запуском вашего запроса, SQL Server будет терпеливо ждать Х миллисекунд, прежде чем очнуться и прервать ваш собственный запрос. Это полезно, когда множество коротких запросов выполняется одновременно, и я не хочу сразу отказаться, но хочу отказаться, если имеется долгоиграющий запрос, который меня блокирует. Если вы передаете значение 0 миллисекунд, SQL Server откажется сразу. Например, в нижеприведенном запросе я пытаюсь удалить все посты Jon Skeet, но хочу прервать мой запрос, если накладываются блокировки, которые останавливают меня либо на таблице Users, либо Posts, и эти блокировки останавливают меня, если время превышает 1 секунду:

SET LOCK_TIMEOUT 1000;
DELETE p
FROM dbo.Users u
INNER JOIN dbo.Posts p ON u.Id = p.OwnerUserId
WHERE u.DisplayName = N'Jon Skeet';

Если вы используете этот метод или другие методы, описанные в этой статье, ваш запрос будет падать с ошибкой, если он блокируется кем-нибудь. Большинство из нас (включая и меня) не сильно старается проверять ошибки и терпеливо повторяют свой запрос; поэтому нам, вероятно, следует потратить час на чтение серии статей Erland Sommarskog по обработке ошибок, чтобы научиться делать это автоматически.

WITH (NOWAIT) - это вроде как установка lock_timeout 0, однако является хинтом табличного уровня, как и NOLOCK. Это означает, что он воздействует только на отдельную таблицу в запросе. Например, в нижеприведенном запросе я пытаюсь удалить все посты Jon Skeet, но я хочу отказаться от своего запроса, если кто-то блокирует таблицу Users - но я готов вечно ждать снятия блокировок на таблице Posts:

DELETE p
FROM dbo.Users u WITH (NOWAIT)
INNER JOIN dbo.Posts p ON u.Id = p.OwnerUserId
WHERE u.DisplayName = N'Jon Skeet';

SET DEADLOCK_PRIORITY LOW - это не о блокировках, а конкретно о тупиках. Когда я выполняю эту установку в начале моего пакета, я как бы говорю: "Я буду ждать снятия блокировок, но если возникнет тупиковая ситуация, приди и убей мой запрос, поскольку я не собираюсь выполнять его снова". Вы вызываете его так же, как будто сделали LOCK_TIMEOUT:

SET DEADLOCK_PRIORITY LOW;
DELETE p
FROM dbo.Users u
INNER JOIN dbo.Posts p ON u.Id = p.OwnerUserId
WHERE u.DisplayName = N'Jon Skeet';

WAIT_AT_LOW_PRIORITY - этот просто для обслуживания индексов, и печально, что он не работает для создания и удаления. "Онлайновая" перестройка индекса не вполне онлайн: ей требуется краткая блокировка модификации схемы, чтобы заменить индекс новой копией. Этот хинт позволяет позволяет вашему завершенному индексу терпеливо дожидаться в фоновом режиме, пока завершаются другие запросы, чтобы потом заменить его:

ALTER INDEX PK_Id ON dbo.Users
REBUILD WITH (ONLINE = ON (
WAIT_AT_LOW_PRIORITY ( MAX_DURATION = 1 MINUTES,
ABORT_AFTER_WAIT = SELF ))
);

Если последний вариант полезен, то следующий шаг - аналогичным образом избежать блокировок с операциями DML, используя статью Kendra Little, об операциях, которые поддерживаются онлайн и возобновляются.

Обратные ссылки

Нет обратных ссылок

Комментарии

Показывать комментарии Как список | Древовидной структурой

Нет комментариев.

Автор не разрешил комментировать эту запись

Добавить комментарий

Enclosing asterisks marks text as bold (*word*), underscore are made via _word_.
Standard emoticons like :-) and ;-) are converted to images.

To prevent automated Bots from commentspamming, please enter the string you see in the image below in the appropriate input box. Your comment will only be submitted if the strings match. Please ensure that your browser supports and accepts cookies, or your comment cannot be verified correctly.
CAPTCHA

Form options

Добавленные комментарии должны будут пройти модерацию прежде, чем будут показаны.