NOLOCK всегда плох?

34

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

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

Поскольку большая часть моего обучения SQL проходила с разными администраторами баз данных с совершенно разными мнениями, я хотел спросить об этом у самых разных администраторов баз данных.

DataGirl
источник
1
Другая сторона этого обсуждения: dba.stackexchange.com/q/2684/2660
Ник Чаммас,

Ответы:

30

Если ваш отчет блокирует обновления, то ваш администратор базы данных прав: вы не должны его использовать NOLOCK. Сам факт того, что есть конфликты является явным признаком того, что , если вы бы использовать грязное чтение вы получите неправильные отчеты.

На мой взгляд, всегда есть лучшие альтернативы, чем NOLOCK:

  • Ваши рабочие таблицы только для чтения и никогда не изменяются? Пометить базу данных только для чтения!
  • Сканирование таблицы вызывает конфликты блокировки? Индексируйте таблицы соответствующим образом, преимущества являются множественными.
  • Не можете изменить / не знаете, как правильно индексировать? Используйте SNAPSHOT ИЗОЛЯЦИЮ .
  • Не можете изменить приложение для использования снимка? Включите чтение совершенного снимка !
  • Вы измерили влияние контроля версий строк и имеете доказательства, что оно влияет на производительность? Вы не можете индексировать данные? а ты в порядке с неверными отчетами ? Тогда, по крайней мере, сделайте себе одолжение и используйте SET TRANSACTION ISOLATION LEVEL, а не подсказку запроса. Позже будет проще исправить уровень изоляции, а не изменять каждый запрос.
Ремус Русану
источник
6
Будьте осторожны: включение моментального снимка с фиксацией может привести к поломке кода.
AK
33

Это не всегда плохо.

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

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

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

По крайней мере, для простых запросов (для одной таблицы) можно отказаться от использования этих проверок и получить упорядоченное сканирование по ключу nolock, просто добавив ORDER BY index_keyк запросу так, чтобы Orderedсвойство IndexScanis было true.

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

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

Мартин Смит
источник
3
+1 - Мы часто используем его, потому что наши производственные таблицы никогда не изменяются.
JNK
@JNK Что ты имеешь в виду, никогда не модифицируется?
Kuberchaun
4
Мартин, я бы предложил немного другие слова: «при чтении зафиксированные значения могут быть как пропущены, так и прочитаны более одного раза». В некоторых экзотических случаях мы можем получить строку более двух раз.
AK
@ StarShip3000 Данные, которые мы развертываем для производства, в основном доступны только для чтения для конечных пользователей, поэтому большинство их представлений имеют подсказки NOLOCK
JNK
11

Ваши клиенты терпят противоречивые результаты в отчетах? Если ответ «нет», вы не должны использовать NOLOCK - вы можете получить неверные результаты при одновременном использовании. Я написал несколько примеров здесь , здесь и здесь . В этих примерах показаны противоречивые выходные данные в режимах READ COMMITTED и REPEATABLE READ, но вы также можете настроить их и получить неверные результаты с NOLOCK.

Аляска
источник
Большинство отчетов, которые я создаю, не основаны на текущих данных. Большинство клиентов работают отчеты вчерашние данные. Изменится ли ваш ответ, если бы это было так?
DataGirl
8

Большинство отчетов, которые я создаю, не основаны на текущих данных. Большинство клиентов работают отчеты вчерашние данные. Изменится ли ваш ответ, если бы это было так?

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

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

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

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

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

Кристиан Шпехт
источник
Мне нравится ваш ответ, и он будет работать - если бы у меня был полный контроль - что я не сделал. Часто я не имею полного контроля и не могу создавать индексы. Мне повезло, если я могу запустить / отобразить планы выполнения.
DataGirl