Преимущества УСТАНОВЛЕННОГО УРОВНЯ ИЗОЛЯЦИИ СДЕЛКИ СЧИТАЮТСЯ

12

Я использую SET TRANSACTION ISOLATION LEVEL READ UNCOMMITTEDв большинстве своих общих запросов SQL, главным образом потому, что это было подробно изучено при первоначальном изучении языка.

WITH (NO LOCK)Насколько я понимаю, этот уровень изоляции действует так же, как и я, когда-либо склонен использовать SET TRANSACTION ISOLATION LEVEL READ UNCOMMITTED.

  • Есть ли когда - нибудь время, когда я должен использовать WITH (NO LOCK)более SET TRANSACTION ISOLATION LEVEL READ UNCOMMITTED.
  • Не SET TRANSACTION ISOLATION LEVEL READ UNCOMMITTEDмешает ли другим пользователям быть заблокированными из таблиц, которые я читаю?
  • Если SET TRANSACTION ISOLATION LEVEL READ UNCOMMITTEDиспользуется для остановки блокировок, но я только читаю данные, какой смысл в этом? Только системные запросы будут генерировать блокировки? Стоит ли использовать его при выполнении запросов, которые возвращаются, скажем, через 5-10 секунд?
  • Мне сказали не использовать SET TRANSACTION ISOLATION LEVEL READ UNCOMMITTEDпри чтении данных, которые будут использоваться в обновлениях, по-видимому, чтобы избежать обновления грязных данных. Будет ли это единственной причиной?
  • С типом базы данных, над которой я работаю, есть среда производства и тестирования. Мы очень редко будем запрашивать производственную среду, но когда мне нужно, я обычно буду использовать SET TRANSACTION ISOLATION LEVEL READ UNCOMMITTEDв своем запросе. Я понимаю, что с этим возможно грязное чтение. Помимо получения данных обратно, которые могут не в конечном итоге быть переданы в базу данных (и, следовательно, выбросить мои результаты), какие другие типы «грязного чтения» могут быть возможны?

Извините за массу вопросов.

dmoney
источник
2
Вы можете прочитать одни и те же данные дважды - это еще один провал. Использование RU или NO LOCK в качестве стандарта - плохая идея.
Джеймс Андерсон
9
Я бы не использовал READ UNCOMMITTEDвезде, точно так же, как я бы не использовал WITH (NOLOCK)везде (по сути, это одно и то же) blogs.sqlsentry.com/aaronbertrand/bad-habits-nolock-everywhere
Марк Синкинсон
1
Посмотрите на модели изоляции SNAPSHOT. Они намного сильнее, чем RCU, а также не блокируют и не вызывают блокировку. Они звучат как хорошая модель по умолчанию для вас (вместо значения по умолчанию для RCU!).
USR

Ответы:

25

Страшно, что ты так научился (извини!).

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

На самом деле, вы рискуете своей честностью. Может случиться, что вы прочитаете строку, которая в данный момент используется для удаления или изменения. Также может показаться, что вы прочитали неправильное значение. Это может быть действительно необычным, но это может случиться. Что я имею в виду с этим? Хорошо, представьте себе строку, которая очень широка (в ней много столбцов и много длинных nvarcharстолбцов). Обновление происходит в этой строке и устанавливает новые значения. В редких случаях с вами может случиться, что вы читаете только пол строки. Например, может произойти и другое, если пользователь изменит свои значения для входа. Он меняет свою почту + пароль. Почта уже установлена, но пароль - нет. Таким образом, у вас есть противоречивое состояние.

Я бы предложил забыть о READ UNCOMMITTED. Просто используйте его там, где это действительно необходимо.

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

Другая идея может быть WITH(READPAST)вместо WITH(NOLOCK). Вы прочитаете старое состояние таблицы (немного похоже на SNAPSHOT ISOLATION), но вместо этого вы пропустите все заблокированные на данный момент строки.

ионный
источник
@ Ионик, большое спасибо за ответ! Я действительно ценю помощь по этому вопросу.
Деньги
@HingeSight, это звучит так, но есть очень хороший шанс, что это была моя интерпретация заявления, в любом случае спасибо за ваш вклад.
Деньги
1
SNAPSHOT ISOLATIONне нужно включать, чтобы включить READ COMMITTED SNAPSHOT. READ COMMITTED SNAPSHOTНеобходимо включить только параметр базы данных, чтобы управление версиями строк вместо блокировок обеспечивало согласованность при чтении, избегая необходимости грязного чтения.
Дан Гусман
Да, я имел в виду, что @DanGuzman. Извините, ответ был немного неясным в этом вопросе. Я редактировал это. :-)
Ionic
С READPAST вы пропустите записи, которые заблокированы, вы не получите старые значения - так что единственное место, где я понял, что это можно использовать, - это обработка очереди
Джеймс З
2

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

  1. При написании и тестировании пакетов служб SSIS SQL Server этапы пакета могут быть включены в транзакцию. Если вы тестируете пакет, выполняя его шаг за шагом в отладчике служб SSIS, вам может потребоваться проверить таблицы, пока в таблице есть блокировки. Использование команды SET TRANSACTION ISOLATION LEVEL READ UNCOMMITTED позволяет использовать SQL Server Manager Studio для проверки таблиц во время отладки пакета.

  2. В SQL Server Manager Studio вы можете протестировать код T-SQL, заключив его в транзакцию, чтобы дать вам возможность откатить изменения. Например, в тестовой базе данных вы можете захотеть восстановить данные в исходное состояние как часть вашего теста. Если вы тестируете код в транзакции и хотите проверить заблокированные таблицы во время выполнения транзакции, вы можете использовать SET TRANSACTION ISOLATION LEVEL READ UNCOMMITTED, чтобы проверить значения в другом окне.

Я принимаю, что это довольно неясное использование READ UNCOMMITTED, но я нашел их полезными в тестовой среде.

Ubercoder
источник
1

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

Конечно, READ UNCOMMITTED(Грязные чтения) может предоставить неверную информацию в этих случаях, но эта информация была правильной 5 секунд раньше.

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

Между тем, в типичной большой, занятой базе данных, в которой отношение чтения к записи составляет 100 (или более) к 1, КАЖДЫЙ одиночный (чтение) запрос, который не использует грязное чтение, замедляет работу системы, поскольку ему необходимо получить и проверить для блокировок И это значительно повышает вероятность сбоя транзакций (обычно из-за тупиковых ситуаций), что может вызвать более серьезные проблемы с целостностью базы данных.

Вместо этого, использование грязного чтения делает систему НАМНОГО быстрее и надежнее (отчасти из-за улучшенной производительности, что снижает вероятность возникновения несоответствий).

Конечно, бывают случаи, когда их не следует использовать. Мне не нравится устанавливать для базы данных значение по умолчанию для использования READ UNCOMMITTEDуровня изоляции или даже использовать явное SET TRANSACTION ISOLATION LEVEL READ UNCOMMITTEDвыражение в начале сценариев SQL и SP - существует слишком большая вероятность того, что Dirty Read произойдет, когда этого не следует делать. Вместо этого (NOLOCK)подсказки являются гораздо лучшим подходом, поскольку они явно указывают, что программист задумался о том, что они делают, и решили, что для этой конкретной таблицы в этом конкретном запросе «грязные чтения» были безопасными.

Если вы программируете приложение для перевода денег с одного банковского счета на другой, вам не следует использовать Dirty Reads. Но большинству приложений такой уровень паранойи не нужен.

Саймон Хольцман
источник