Лучшая ситуация для использования READ UNCOMMITTED уровня изоляции

10

Как мы все знаем, READ UNCOMMITTED - это самый низкий уровень изоляции, при котором могут возникать такие вещи, как грязное чтение и фантомное чтение. Когда лучше всего использовать этот уровень изоляции и по каким причинам его можно использовать?

На самом деле я читал ответы раньше, но я не мог понять это полностью, потому что было недостаточно примеров.

Питер Мортенсен
источник

Ответы:

20

Я использую READ_UNCOMMITTED(или NOLOCK) при запросе производственных баз данных из SSMS, но не из кода приложения. Эта практика (наряду с подсказкой запроса MAXDOP 1) помогает гарантировать, что случайные запросы для анализа данных и устранения неполадок не влияют на рабочую нагрузку, с пониманием, что результаты могут быть неверными.

К сожалению, я вижу READ_UNCOMMITTED/ NOLOCKшироко использую в производственном коде, чтобы избежать блокирования за счет целостности данных. Правильным решением является уровень изоляции версий строк ( SNAPSHOTили READ_COMMITTEDс READ_COMMITTED_SNAPSHOTопцией базы данных ON) и / или внимание к настройке запросов и индексов.

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

Дэн Гусман
источник
7

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

Что касается других вариантов, я бы подтолкнул людей к использованию Read Committed Snapshot Isolation (RCSI) для новых приложений или SNAPSHOT ISOLATION (SI) для более старых приложений, где вы не можете легко протестировать всю базу кода для условий гонки с RCSI.

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

Если у вас нет администратора базы данных или кого-либо, чья работа заключается в мониторинге и управлении вашим SQL Server, эти варианты могут быть опасными. В целом, не все имеют полный контроль над кодом, отправляемым на их сервер, где они могут изменить строку подключения или код, чтобы запросить SI для проблемных запросов.

Кроме того, у большинства людей нет проблем с блокировкой всего приложения . У них проблемы с такими вещами, как отчетность по данным OLTP. Если вы можете согласиться с компромиссами NOLOCK / RU в обмен на те отчеты, которые не были заблокированы авторами, сделайте это.

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

И, конечно, если ваша проблема заключается в блокировке записи / записи, единственная опция, которая поможет, это SI, но потребовалось бы невероятное количество работы разработчика, чтобы правильно реализовать ее с обработкой ошибок и т. Д.

Эрик Дарлинг
источник
5
И если проблема на самом деле заключается в том, чтобы просто сообщать о данных OLTP, перегрузите их в какой-нибудь вторичный доступ только для чтения (AG, доставку журналов, репликацию или проверку по собственному усмотрению).
Аарон Бертран
3
@AaronBertrand И тогда у них будет второй сервер для мониторинга;)
Эрик Дарлинг
5

ИМХО, единственно верный вариант использования READ UNCOMMITTED в современной системе - это при отладке одного сеанса из другого в процессе разработки, чтобы вы могли видеть, что он делает, например, когда сохраненный процесс еще работает. Он никогда не будет использоваться в производственной системе. Может быть небольшой прирост производительности, но в долгосрочной перспективе это никогда не будет стоить того.

Gaius
источник
3

Мы используем его в здравоохранении постоянно.

Удивительно редко, когда отдельные строки данных изменяют средний запрос, и отношение чтения / записи составляет примерно 10 000/1 - и большинство из них являются вставками, а не обновлениями. Например, когда лабораторный интерфейс записывает лабораторные результаты пациента в базу данных, эти значения никогда не изменятся.

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

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

За 10 лет здравоохранения SQL я никогда не видел Rollback Transaction. Я хочу входить и выходить, не нарушая работу конечного пользователя. Если существует высокий риск замедления работы базы данных OLTP и низкий риск получения неверных данных, я сделаю NOLOCK.

Должны ли мы использовать это? Может быть, а может и нет. Вообще говоря, я бы не сказал, что многие базы данных приложений, над которыми я работал, хорошо спроектированы. Они обычно забиты анти-шаблонами.

Джеймс
источник
4
просто к сведению, можно прочитать частично написанные строки с Nolock.
Макс Вернон
1
Уф! Мне действительно нужно, чтобы мой босс купил мне другой сервер, чтобы я мог отправить этот материал ...
Джеймс
3
Возможно, вас заинтересует это изящное сообщение в блоге Пола Уайта о READ UNCOMMITTED, особенно в разделе «Чтение поврежденных данных»: чтение уровня непринятой изоляции
Джош Дарнелл,
1

READ_UNCOMMITTED/NOLOCKЭто хороший вариант, когда точность данных не является главной целью. Иногда, когда приблизительный совокупный счет - это все, что требуется. Например: существуют хранимые процедуры, которые используются для таблиц INSERT или UPDATE. Иногда количество обновляемых или вставляемых записей огромно (тысячи записей). Во время этих запусков хранимых процедур мы можем NOLOCKпериодически запускать простой запрос на выборку для целевой таблицы, чтобы увидеть, будет ли он гладко прогрессировать (Для запроса на обновление, если у вас есть столбец изменения состояния для обновляемых записей, мы можем использовать этот столбец для запуска group byзапроса с NOLOCKчтобы узнать, постоянно ли изменяется счетчик изменений статуса).

GirKarr
источник
0

Имейте в виду, что READ UNCOMMITTED создает дополнительные проблемы согласованности, а не только грязные чтения. В зависимости от метода доступа вы можете пропустить строки или даже прочитать одну и ту же строку более одного раза. Если вас интересуют подробности, прочитайте статью Ицик Бен-Гана

SQLRaptor
источник
3
Пропуск строк и чтение строк более одного раза возможно и на уровне фиксации чтения по умолчанию. Если столбец ключа индекса обновляется во время сканирования и он перемещается.
Мартин Смит
Побочная дискуссия по этому ответу была перенесена в чат .
Пол Уайт 9