Является ли NOLOCK (подсказка Sql Server) плохой практикой? - PullRequest
119 голосов
/ 21 сентября 2009

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

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

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

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

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

Ответы [ 12 ]

103 голосов
/ 21 сентября 2009

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

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

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

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

Если ответ «нет», используйте NOLOCK для повышения производительности. <ч /> Я только что выполнил быстрый поиск по ключевому слову NOLOCK в базе кода для переполнения стека и нашел 138 экземпляров, поэтому мы используем его во многих местах.

65 голосов
/ 21 сентября 2009

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

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

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

20 голосов
/ 21 сентября 2009

Если вас не волнует грязное чтение (т. Е. В ситуации преимущественно чтения), то NOLOCK хорошо.

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

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

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

13 голосов
/ 23 февраля 2011

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

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

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

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

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

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

Использование подсказки NOLOCK в EF4?

9 голосов
/ 18 августа 2010

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

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

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

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

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

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

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

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

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

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

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

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

2 голосов
/ 08 февраля 2014

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

  • Реплицируйте ваши данные (используя репликацию журнала) в базу данных отчетов.
  • Используйте снимки SAN и смонтируйте согласованную версию DB
  • Используйте базу данных с лучшим базовым уровнем изоляции транзакций

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

2 голосов
/ 05 февраля 2013

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

2 голосов
/ 21 декабря 2012

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

2 голосов
/ 23 февраля 2011

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

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

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

1009 * Люк *

...