Является ли NOLOCK (подсказка Sql Server) плохой практикой?

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

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

Мне также сказали, что это отличное решение, если я испытываю тупики. Итак, я начал следовать этой мысли в течение нескольких лет, пока гуру по SQL не помог мне со случайным кодом и не заметил все NOLOCKS в моем SQL-коде. Меня вежливо ругали, и он пытался объяснить это мне (почему это нехорошо), и я как-то заблудился. Я чувствовал, что суть его объяснения состояла в том, что "это бандитское решение более серьезной проблемы... особенно, если вы испытываете взаимоблокировку". Таким образом, исправьте корень проблемы ".

Недавно я немного погуглил по этому поводу и наткнулся на этот пост.

Так, может, какой-нибудь гуру-сэнсей, пожалуйста, просветите меня?

12 ответов

Решение

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

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

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

До работы над переполнением стека я был против NOLOCK на основной, что вы могли бы потенциально выполнить SELECT с NOLOCK и получить результаты с данными, которые могут быть устаревшими или противоречивыми. Нужно подумать о том, сколько записей может быть вставлено / обновлено одновременно, когда другой процесс может выбирать данные из той же таблицы. Если это часто случается, то существует высокая вероятность взаимоблокировок, если вы не используете режим базы данных, такой как READ COMMITED SNAPSHOT,

С тех пор я изменил свою точку зрения на использованиеNOLOCKувидев, как это можно улучшитьSELECTпроизводительность, а также устранение взаимоблокировок на массивно загруженном SQL Server. Временами вы можете не заботиться о том, что ваши данные не являются полностью зафиксированными на 100%, и вам нужны быстрые результаты, даже если они устарели.

Задайте себе вопрос, думая об использовании NOLOCK:

Включает ли мой запрос таблицу с большим числомINSERT /UPDATEКоманды и мне все равно, если данные, возвращенные из запроса, могут пропустить эти изменения в данный момент?

Если ответ нет, используйтеNOLOCKулучшить производительность.


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

Если вас не волнует грязное чтение (то есть в ситуации, в которой обычно выполняется чтение), тогда NOLOCK Это хорошо.

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

И объяснение гуру было правильным. Обычно это лейкопластырь для решения более серьезной проблемы.

Редактировать: я определенно не предлагаю использовать NOLOCK. Полагаю, мне следовало ясно это объяснить. (Я бы использовал его только в экстремальных обстоятельствах, когда я анализировал, что все в порядке). Как пример, некоторое время назад я работал над некоторыми TSQL, которые были добавлены в NOLOCK, чтобы попытаться устранить проблемы с блокировками. Я удалил их все, внедрил правильные индексы, и ВСЕ тупики исчезли.

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

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

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

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

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

РЕДАКТИРОВАТЬ: это не просто тупики, это помогает, это также, сколько вы собираетесь заставить всех остальных ждать, пока вы не закончите, или наоборот.

Используете подсказку NOLOCK в EF4?

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

  • При запросе отдельных значений / строк всегда плохая практика - использовать NOLOCK - вам, вероятно, никогда не захочется отображать неверную информацию или даже предпринимать какие-либо действия с неверными данными.
  • При отображении приблизительной статистической информации NOLOCK может быть очень полезен. Возьмите SO в качестве примера: было бы бессмысленно использовать блокировки, чтобы прочитать точное количество просмотров вопроса или точное количество вопросов для тега. Никого не волнует, если вы сейчас неправильно указали 3360 вопросов, помеченных "sql-сервером", а из-за отката транзакции - 3359 вопросов через секунду.

Я согласен с некоторыми комментариями по поводу подсказки NOLOCK, особенно с теми, кто говорит: "используйте его, когда это уместно". Если приложение написано плохо и использует параллелизм ненадлежащим образом - это может привести к эскалации блокировки. Очень транзакционные таблицы также постоянно блокируются из-за их характера. Хорошее покрытие индекса не поможет с извлечением данных, но настройка ISOLATION LEVEL для READ UNCOMMITTED делает. Также я считаю, что использование подсказки NOLOCK безопасно во многих случаях, когда характер изменений предсказуем. Например - в производстве, когда задания с путешественниками проходят через различные процессы с большим количеством вставок измерений, вы можете безопасно выполнить запрос к законченному заданию с подсказкой NOLOCK и таким образом избежать столкновения с другими сеансами, которые ставят блокировки PROMOTED или EXCLUSIVE на таблицу. / стр. Данные, к которым вы получаете доступ в этом случае, являются статическими, но они могут находиться в очень транзакционной таблице с сотнями миллионов записей и тысячами обновлений / вставок в минуту. ура

Я считаю, что практически никогда не правильно использовать nolock.

Если вы читаете одну строку, то правильный индекс означает, что вам не понадобится NOLOCK, так как отдельные действия строки выполняются быстро.

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

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

Ошибки, которые возможны под NOLOCK:

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

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

Поэтому: если вы "знаете", что строка не изменится во время работы, не используйте nolock, так как индекс обеспечит эффективный поиск.

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

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

Как профессиональный разработчик, я бы сказал, что это зависит. Но я определенно следую советам GATS и OMG Ponies. Знайте, что вы делаете, знайте, когда это помогает, а когда - и

читать подсказки и другие плохие идеи

Что может заставить вас глубже понять сервер SQL Я обычно придерживаюсь правила, что SQL-подсказки являются ЗЛО, но, к сожалению, я использую их время от времени, когда мне надоело заставлять SQL-сервер делать что-то... Но это редкие случаи.

Люк

Лучшие решения, когда это возможно:

  • Реплицируйте ваши данные (используя log-replication) в базу данных отчетов.
  • Используйте снимки SAN и смонтируйте согласованную версию БД
  • Используйте базу данных, которая имеет лучший фундаментальный уровень изоляции транзакций

Уровень изоляции транзакции SNAPSHOT был создан, потому что MS теряла продажи Oracle. Oracle использует журналы отмены / повтора, чтобы избежать этой проблемы. Postgres использует MVCC. В будущем Heckaton от MS будет использовать MVCC, но через несколько лет он не будет готов к производству.

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

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

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

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

Это связано с тем, что другие транзакции перемещают данные одновременно с чтением.

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

В реальной жизни, когда вы сталкиваетесь с системами, уже написанными и добавляющими индексы в таблицы, а затем резко замедляющими загрузку данных из таблицы данных в 14 гига, вы иногда вынуждены использовать WITH NOLOCK в своих отчетах и ​​выполнять обработку в конце месяца, чтобы совокупные функции (сумма, подсчет и т. д.) не выполняйте блокировку строк, страниц, таблиц и не определяйте общую производительность. Легко сказать, что в новой системе никогда не используйте WITH NOLOCK и не используйте индексы - но добавление индексов серьезно снижает загрузку данных, и когда мне тогда говорят, ну, в общем, измените базу кода, чтобы удалить индексы, затем выполните массовую загрузку, а затем заново создайте индексы - что все хорошо, если вы разрабатываете новую систему. Но не тогда, когда у вас уже есть система.

Другие вопросы по тегам