Как воспроизвести «Не удалось продолжить сканирование с NOLOCK из-за перемещения данных»

10

Иногда я получаю сообщение «Не удалось продолжить сканирование NOLOCKиз-за перемещения данных» с некоторыми большими заданиями, которые выполняются WITH (NOLOCK)в запросах выбора.

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

Как бы я воспроизвести это?

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

Когда это происходит, повторное выполнение запроса приводит к успеху - поэтому у меня нет особых опасений по поводу того, что реальные данные или база данных будут постоянно повреждены. Некоторые таблицы в запросе (вместе с их индексами) часто удаляются, воссоздаются и заполняются, поэтому я предполагаю, что это как-то связано с этим.

Удаление NOLOCK- это моя долгосрочная проблема. Во NOLOCK-первых, причина была в том, что запросы были настолько плохими, что они зашли в тупик с ежедневными транзакциями, поэтому NOLOCKбыла и пластырь, чтобы остановить взаимные блокировки (что сработало). Поэтому мне нужен лейкопластырь на лейкопластыре, пока мы не сможем сделать окончательное решение.

Если бы я мог воспроизвести это с Hello World, я бы планировал, возможно, нанести пластырь на работу менее чем за час. Не могу выполнить удаление с поиском и заменой NOLOCK, потому что я снова начну получать блокировки приложений, что для меня хуже, чем случайная неудачная работа.

Хорошая возможность - использовать изоляцию моментальных снимков с фиксацией чтения - мне нужно будет поработать с нашей командой базы данных, чтобы получить более подробную информацию об этом. Частично наша проблема заключается в том, что у нас нет эксперта по SQL Server, который бы справлялся с подобными вещами, и я недостаточно хорошо понимаю уровни изоляции, чтобы сделать это изменение прямо сейчас.

wookie23
источник
1
Рассматривали ли вы просто увольнение NOLOCKс этих рабочих мест? 601 должен меньше всего волновать вас, если результаты этих запросов должны быть точными . Пол Уайт показывает особенно ужасный пример чтения данных, который не должен быть здесь возможным .
Аарон Бертран
3
Вы можете установить DEADLOCK_PRIORITYзначение LOWв заданиях, чтобы при возникновении взаимоблокировок сбой заданий, а не приложений. После этого вы можете исследовать тупики и выяснить, почему они происходят, и решить эту проблему. Это может быть очень простое исправление, например, поменять местами порядок двух операторов. Какова бы ни была проблема, NOLOCKэто не решение , поэтому перестаньте пытаться заставить ее быть только потому, что это проще всего.
Аарон Бертран
@AaronBertrand Спасибо, не знал о DEADLOCK_PRIORITY - я посмотрю на это. Мы попытались отследить взаимоблокировки, но они возникали в разное, казалось бы, случайное время, и только один или два раза в день, и никогда не воспроизводились по требованию - наши запланированные задания выполняют десятки тысяч запросов каждый час, а наше приложение выполняет сотни запросов всякий раз, когда он просто загружает страницу или что-то сохраняет, и мы не отследили, какой запрос с обеих сторон вовлечен в тупик. Я не собирался оставлять NOLOCK там навсегда, поэтому мы ищем лучшие долгосрочные решения.
wookie23
1
Вы упомянули, что вам было трудно выследить тупики. Учитывая, что вы находитесь в 2008 R2, вы можете посмотреть здесь: sqlservercentral.com/articles/deadlock/65658 Джонатан Кейайас перебирает информацию о взаимоблокировке из кольцевого буфера.
Кеннет Фишер
Ответы и комментарии хорошо решают основную проблему, но вы все еще заинтересованы в том, чтобы найти способ воспроизвести это как интеллектуальное упражнение?
Джеймс Л

Ответы:

8

Так как одна потенциальная «помощь группы» для проблем NOLOCK - это прекратить использование NOLOCK и начать использовать изоляцию READ_COMMITTED_SNAPSHOT, я хочу указать вам на пост в блоге на http://www.brentozar.com Кендры Литтл: « Выполнение снимка» или «Выполнение чтения» Изоляция моментальных снимков в SQL Server: руководство .

Kendra предоставляет достаточно подробную информацию о преимуществах и рисках, используя уровень изоляции READ_COMMITTED_SNAPSHOT.

  1. Этот уровень изоляции становится уровнем изоляции по умолчанию для кода базы данных.
  2. Для изменения уровня изоляции READ_COMMITTED_SNAPSHOT необходимо иметь только одного пользователя в базе данных.
  3. Даже если вы используете READ_COMMITTED_SNAPSHOT изоляцию, вам все равно придется удалить подсказки NOLOCK, поскольку они переопределяют значение по умолчанию.
  4. У некоторых из вашего кода вполне могут быть проблемы, которые требуют решения.

Несколько лет назад мы внедрили изоляцию READ_COMMITTED_SNAPSHOT в базе данных, которая сильно страдала от блокировок . Но как только мы изменили уровень изоляции, у нас начались тупики в нескольких критических областях.

Почему это случилось? Поскольку предыдущий уровень изоляции вызывал сильную блокировку, код мог «никогда» не достичь точки взаимоблокировки. Однако с изоляцией READ_COMMITTED_SNAPSHOT запросы могут продолжать двигаться вперед. Однако некоторый процент больше не ожидающих транзакций начал взаимоблокировку.

К счастью, наш случай был быстро решен путем определения тупиковых точек и корректировки индексов для пары таблиц, чтобы получить более рациональный порядок столбцов. Это значительно уменьшило наши проблемы с блокировкой.

ДКП
источник