Зачем использовать уровень изоляции READ UNCOMMITTED?

225

На простом английском языке, каковы недостатки и преимущества использования

SET TRANSACTION ISOLATION LEVEL READ UNCOMMITTED

в запросе для приложений .NET и приложений служб отчетов?

Кип Реал
источник

Ответы:

210

Этот уровень изоляции допускает грязное чтение. Одна транзакция может видеть незафиксированные изменения, сделанные другой транзакцией.

Чтобы поддерживать наивысший уровень изоляции, СУБД обычно получает блокировки данных, что может привести к потере параллелизма и высоким издержкам блокировки. Этот уровень изоляции расслабляет это свойство.

Вы можете проверить статьюREAD UNCOMMITTED в Википедии для нескольких примеров и дальнейшего чтения.


Возможно, вас также заинтересует статья Джеффа Этвуда в блоге о том, как он и его команда боролись с тупиковой ситуацией в первые дни переполнения стека. По словам Джеффа:

Но это nolockопасно? Не могли бы вы в конечном итоге прочитать недействительные данные с помощью read uncommitted? Да, в теории. Вы не найдете недостатка в астронавтах с архитектурой баз данных, которые начнут бросать на вас науку ACID, и почти просто активируют пожарную сигнализацию здания, когда вы говорите им, что хотите попробовать nolock. Это правда: теория страшна. Но вот что я думаю: «В теории нет разницы между теорией и практикой. На практике есть».

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

Но на практике добавление nolockк запросам, которые вы точно знаете, является простым, простым делом, доступным только для чтения, и, кажется, никогда не приводит к проблемам ... Пока вы знаете, что делаете.

Одной альтернативой READ UNCOMMITTEDуровню, который вы можете рассмотреть, является READ COMMITTED SNAPSHOT. Цитирую Джеффа снова:

Снимки основаны на совершенно новом методе отслеживания изменений данных ... это не просто небольшое логическое изменение, оно требует, чтобы сервер обрабатывал данные физически по-другому. Как только этот новый метод отслеживания изменений данных включен, он создает копию или снимок каждого изменения данных. Благодаря чтению этих снимков, а не живых данных во время конфликта, Shared Locks больше не нужны при чтениях, и общая производительность базы данных может увеличиться.

Даниэль Вассалло
источник
13
Автор, похоже, подразумевает, что чтение без подтверждения / без блокировки вернет все данные, которые были зафиксированы в последний раз. Насколько я понимаю, чтение незафиксированным вернет любое значение, которое было установлено в последний раз, даже из незафиксированных транзакций. Если это так, результат не будет извлекать данные "несколько секунд устарели". Было бы (или, по крайней мере, могло бы, если транзакция, которая записывала прочитанные вами данные, откатываться) получать данные, которые не существуют или никогда не были зафиксированы. Я ошибаюсь?
xr280xr
4
Отличный ответ. Кстати, Oracle имеет «снимок» по умолчанию, так как я знаю его, вероятно, за десятилетия до того, как Sql Server представил его. Я был очень разочарован, когда начал работать с SQL Server, и обнаружил, что все проблемы параллелизма были решены с использованием «примитивных» механизмов блокировки. Никогда не видел "Чтение незафиксированного" в Oracle. И практикующие так же счастливы, как и космонавты.
Стефан Штайнеггер
13
READ UNCOMMITTEDтакже может заставить вас читать строки дважды или пропустить целые строки . Если во время чтения происходит разделение страницы, вы можете пропустить целые куски данных. WITH(NOLOCK)следует использовать, только если точность результатов не важна
Ян Бойд
8
@DanielNolan, рекомендовать эту статью опасно, потому что Джефф не знал, что делает . Только чтение не имеет смысла, поскольку чтение данных никогда не будет изменено. Попытка использовать это для чтения таблиц, в которые будут записываться, означает, что на практике вы будете читать то, что откатывается. Дело не только в том, что вы читаете данные, которым несколько секунд, но вы .................................. ................... ........................... ....
Pacerier
5
................................... читает данные , которые никогда даже получают совершенные. Это само определение искаженного чтения. И если вы собираетесь писать на основе результатов этих незафиксированных чтений, на практике вы будете писать поврежденные данные. Также в статье говорится, что «MySQL, который вырос на веб-приложениях, гораздо менее пессимистичен, чем SQL Server». Неверно, Sql Server по умолчанию работает на уровне чтения-чтения, в то время как MySQL работает на повторяющемся-чтении по умолчанию, на пяти уровнях от чтения-незафиксированного.
Pacerier
36

Это может быть полезно, чтобы увидеть ход выполнения длинных запросов на вставку, сделать приблизительные оценки (например, COUNT(*)грубые SUM(*)) и т. Д.

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

Quassnoi
источник
36

Мой любимый вариант использования для read uncommitedотладки чего-то, что происходит внутри транзакции.

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

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

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

Невиш
источник
6
Моя компания любит делать излишне сложные хранимые процедуры. Какая отличная идея для устранения неполадок!
Брэндон
22

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

Если вы заботитесь о точности, не используйте это.

Больше информации на MSDN :

Реализует грязное чтение или изоляцию уровня 0, что означает, что никакие общие блокировки не выдаются и никакие исключительные блокировки не учитываются. Когда эта опция установлена, возможно чтение незафиксированных или грязных данных; значения в данных могут быть изменены, и строки могут появляться или исчезать в наборе данных до окончания транзакции. Этот параметр имеет тот же эффект, что и установка NOLOCK для всех таблиц во всех инструкциях SELECT в транзакции. Это наименее ограничивающий из четырех уровней изоляции.

Марк Байерс
источник
Как это повлияет на скорость запроса?
Кип Реал
11
@Kip - selectоператорам не нужно ждать, чтобы получить общие блокировки для ресурсов, которые блокируются исключительно другими транзакциями.
Джаррод Диксон
15

Когда это нормально использовать READ UNCOMMITTED?

Практическое правило

Хорошо : большие сводные отчеты, показывающие постоянно меняющиеся итоги.

Рискованно : Почти все остальное.

Хорошей новостью является то, что большинство отчетов только для чтения попадают в эту категорию « Хорошие ».

Более детально...

Хорошо, чтобы использовать это:

  • Почти все пользовательские сводные отчеты по текущим нестатическим данным, например, годовой объем продаж. Это рискует предел погрешности (возможно, <0,1%), который намного ниже, чем другие факторы неопределенности, такие как ошибка ввода или просто случайность, когда именно данные записываются каждую минуту.

Это охватывает, вероятно, большую часть того, что будет делать отдел бизнес-аналитики, скажем, в SSRS. Исключением, конечно, является что-либо со знаками $ перед ним. Многие люди относятся к деньгам с гораздо большим рвением, чем к соответствующим базовым показателям, необходимым для обслуживания клиентов и получения этих денег. (Я виню бухгалтеров).

Когда рискованно

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

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

  • Почти все, что кормит приложение, которое также имеет возможности записи.

Когда даже сценарий ОК не в порядке.

  • Какие-либо приложения или процессы обновления используют большие одиночные транзакции? Те, которые удаляют, а затем повторно вставляют много записей, о которых вы сообщаете? В этом случае вы действительно не можете использовать NOLOCKэти таблицы ни для чего.
Adamantish
источник
Хороший вопрос об отчетах. На самом деле, первая мысль, которая пришла мне в голову, была, если я должен использовать read uncommittedдля веб-приложений, когда пользователь видит какую-то сетку пользовательского интерфейса, где точность данных не так важна. Пользователь просто хочет получить краткий обзор того, какие записи могут быть там, и, возможно, с некоторой подкачкой, сортировкой и фильтрацией. Только когда пользователь нажимает кнопку «Изменить», я пытаюсь прочитать самую последнюю запись с более строгим уровнем изоляции. Разве такой подход не должен быть лучше с точки зрения производительности?
JustAMartin
Да, я думаю, что это разумно. Помните, что более важной проблемой является проверка того, что данные не были изменены кем-то еще между моментом нажатия кнопки редактирования и временем отправки. Вы можете справиться с этим, запустив транзакцию, извлекающую данные, как select item from things with (UPDLOCK). Установите короткий тайм-аут, чтобы, если он не может быстро получить блокировку, он сообщал пользователю, что он редактируется. Это защитит вас не только от пользователей, но и от разработчиков. Единственная проблема в том, что вы должны начать думать о тайм-аутах и ​​о том, как вы справляетесь с этим в пользовательском интерфейсе.
Adamantish
6

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

Хью Сигрейвс
источник
4

Используйте READ_UNCOMMITTED в ситуации, когда источник вряд ли изменится.

  • При чтении исторических данных. например, некоторые журналы развертывания, которые произошли два дня назад.
  • При чтении метаданных снова. Например, приложение на основе метаданных.

Не используйте READ_UNCOMMITTED, если вы знаете, что souce может измениться во время операции извлечения.

нео
источник
1
Я чувствую обратное. Во-первых, статические данные должны читаться без каких-либо блоков. Если же блок , то теперь вы обнаружили , что есть важная проблема висит сделку исправить. Кроме того, пользователи будут ожидать, что это будет соответствовать последнему десятичному знаку, независимо от того, что они напечатали для годового отчета за прошлый год. Как правило, они не ожидают, что те же сообщения, о которых они знают, постоянно меняются. Это не относится к подробной, чрезвычайно чувствительной ко времени или финансовой отчетности, но если допустима 1 ошибка ввода в 1000, то так и есть READ UNCOMMITTED.
Adamantish
TLDR: если данные не изменятся, вам не нужно читать UNCOMMITTED, потому что блоков в любом случае нет. Если вы ошибаетесь и все меняется, то хорошо, что вы заблокировали пользователям получение более грязных данных, чем ожидалось.
Adamantish
Да, я склонен согласиться с @Adamantish здесь - вы можете извлечь READ UNCOMMITTEDбольшую пользу из ситуаций, когда ваши данные активно используются, и вы хотите уменьшить нагрузку на сервер, чтобы избежать возможных тупиковых ситуаций и откатов транзакций только потому, что некоторые пользователи по неосторожности злоупотребляют » Обновить »на веб-странице с сеткой данных. Пользователи, которые одновременно просматривают несколько записей, обычно не заботятся о том, являются ли данные немного устаревшими или частично обновленными. Только когда пользователь собирается редактировать запись, вы можете предоставить ему наиболее точные данные.
JustAMartin
2

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

Также интересно отметить, что не происходит. READ UNCOMMITTED не только игнорирует другие блокировки таблиц. Это также не вызывает никаких замков самостоятельно.

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

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

Так что, если для вас очень важно, чтобы данные могли быть вставлены во время выполнения SELECT, READ UNCOMMITTED может иметь смысл. Вы должны учитывать, что ваш отчет может содержать некоторые ошибки, но если он основан на миллионах строк, и только некоторые из них обновляются при выборе результата, это может быть «достаточно хорошо». Ваша транзакция может также потерпеть неудачу все вместе, так как уникальность строки не может быть гарантирована.

Лучше всего может быть использование SNAPSHOT ISOLATION LEVEL, но ваши приложения могут нуждаться в некоторых корректировках, чтобы использовать это. Одним из примеров этого является то, что ваше приложение использует эксклюзивную блокировку строки, чтобы другие пользователи не могли ее прочитать и перейти в режим редактирования в пользовательском интерфейсе. УРОВЕНЬ ИЗОЛЯЦИИ SNAPSHOT также имеет значительное снижение производительности (особенно на диске). Но вы можете преодолеть это, бросая аппаратное обеспечение на проблему. :)

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

Олле Йоханссон
источник
0

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

Sofian
источник
-7

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

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

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

Так что зайдите в Dirty Reads (специально для больших отчетов), ваше программное обеспечение будет работать более плавно ...

Clive
источник
6
Это очень неточно и касается только тех проблем, которые могут возникнуть при использовании nolock. Страницы могут быть разделены, объединения могут потерпеть неудачу, вы можете прочитать несуществующие данные или дублировать данные. Нет никакого способа сделать его использование надежным: вы не можете доверять точности чего-либо под этим уровнем изоляции. READ COMMITTED SNAPSHOT - менее опасная «фальшивая панацея»
Марк Совул
@MarkSowul понижение этого ответа мне кажется несправедливым. @Clive было ясно, что он переключится Committedна вставки и обновления. Что касается других проблем, он также продемонстрировал осведомленность о проблемах разбиения страниц при упоминании использования автоинкрементного ключа. Я согласен с ним в том, что почти все живые репортажи, сделанные только для чтения человеком, могут допускать небольшие расхождения в последнем десятичном знаке. Я согласен, что для подробных списков или данных, предназначенных для машинного чтения и преобразования, это другая история, как и для Клайва.
Adamantish
1
Этот комментарий также демонстрирует отсутствие полного понимания возможных проблем, связанных с nolock. «Незначительные расхождения в последнем десятичном знаке» едва покрывают это. Даже касание «просто использовать чтение, зафиксированное для вставок / обновлений» неверно в качестве общего совета (что если это «вставить запись, если она не существует»?). В любом случае, «читать непринятые] быстро с наименьшим количеством проблем» категорически неправильно.
Марк Совул
Для справки, я согласен с вашим ответом, Adamantish: примерно точные агрегации и немного другое.
Марк Совул