Вопрос

Может ли кто-нибудь объяснить последствия использования with (nolock) по запросам, когда следует/не следует его использовать?

Например, если у вас есть банковское приложение с высокой скоростью транзакций и большим количеством данных в определенных таблицах, для каких типов запросов подойдет nolock?Есть ли случаи, когда его следует всегда использовать/никогда не использовать?

Это было полезно?

Решение

С (NOLOCK) эквивалентно использованию READ UNCOMMITED в качестве уровня изоляции транзакции.Таким образом, вы рискуете прочитать незафиксированную строку, которая впоследствии будет откатана, т.е.данные, которые никогда не попадали в базу данных.Таким образом, хотя это может предотвратить блокировку чтения другими операциями, это сопряжено с риском.ИМХО, в банковском приложении с высоким уровнем транзакций это, вероятно, не будет правильным решением любой проблемы, которую вы пытаетесь решить с его помощью.

Другие советы

Вопрос в том, что хуже:

  • тупик или
  • неправильное значение?

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

В финансовой базе данных вы используете бизнес-операции.Это означает добавление одной строки в каждую учетную запись.Крайне важно, чтобы эти транзакции были завершены и строки были успешно записаны.

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

Тем не менее, SQL Server 2005 исправил большинство ошибок, из-за которых NOLOCK необходимый.Поэтому, если вы не используете SQL Server 2000 или более раннюю версию, он вам не понадобится.

Дальнейшее чтение
Управление версиями на уровне строк

Учебным примером законного использования подсказки nolock является выборка отчетов из базы данных OLTP с высоким уровнем обновления.

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

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

Проверить Статья Ицика Бен-Гана.Вот отрывок:

«С подсказкой NoLock (или установлением уровня изоляции сеанса для чтения незавершенных) вы сообщаете SQL Server, что не ожидаете согласованности, поэтому нет никаких гарантий.Имейте в виду, что «противоречивые данные» не только означают, что вы можете увидеть незавершенные изменения, которые были позже откачены, или изменения данных в промежуточном состоянии транзакции. Это также означает, что в простом запросе, который сканирует все данные таблицы/индекса SQL Server может потерять позицию сканирования, или вы можете в конечном итоге получить одну и ту же строку дважды. "

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

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

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

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

Справедливости ради, вот два особых сценария, в которых подсказка nolock может оказаться полезной.

1) База данных сервера sql до 2005 года, которой необходимо выполнить длинный запрос к активной базе данных OLTP, это может быть единственным способом

2) Плохо написанное приложение, которое блокирует записи и возвращает управление пользовательскому интерфейсу и читателям, блокируется на неопределенный срок.Nolock может быть здесь полезен, если приложение не может быть исправлено (стороннее и т. д.), а база данных либо старше 2005 года, либо невозможно включить управление версиями.

NOLOCK эквивалентно READ UNCOMMITTED, однако Microsoft заявляет, что вам не следует использовать его для UPDATE или DELETE заявления:

Для операторов UPDATE или DELETE:Эта функция будет удалена в будущей версии Microsoft SQL Server.Избегайте использования этой функции в новых разработках и запланируйте изменение приложений, которые в настоящее время используют эту функцию.

http://msdn.microsoft.com/en-us/library/ms187373.aspx

Эта статья относится к SQL Server 2005, поэтому поддержка NOLOCK существует, если вы используете эту версию.Чтобы подготовить свой код к будущему (при условии, что вы решили использовать грязное чтение), вы можете использовать это в своих хранимых процедурах:

SET TRANSACTION ISOLATION LEVEL READ UNCOMMITTED

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

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

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

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

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

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

Простой ответ — всякий раз, когда ваш SQL не изменяет данные и у вас есть запрос, который может помешать другим действиям (посредством блокировки).

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

Это особенно полезно, если у вас есть отчеты типа OLAP, которые вы используете для базы данных OLTP.

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

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

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

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

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

Короткий ответ:

Никогда не используйте WITH (NOLOCK).

Длинный ответ:

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

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

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

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

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

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

Можно возразить, что его можно использовать там, где это сойдет с рук, но какой в ​​этом смысл?Я не могу вспомнить ни одной ситуации, в которой допустимы поврежденные данные.

Никогда и никогда не используйте NOLOCK.

(всегда)

Используйте nolock, когда вас устраивают «грязные» данные.Это означает, что nolock также может читать данные, которые находятся в процессе изменения и/или незафиксированные данные.

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

Я использую подсказку with (nolock), особенно в базах данных SQLServer 2000 с высокой активностью.Однако я не уверен, что это необходимо в SQL Server 2005.Недавно я добавил эту подсказку в SQL Server 2000 по просьбе администратора базы данных клиента, поскольку он заметил множество блокировок записей SPID.

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

Кстати, базы данных, с которыми я имею дело, являются серверной частью корпоративных систем медицинских претензий, поэтому речь идет о миллионах записей и более чем 20 таблицах во многих объединениях.Обычно я добавляю подсказку С (nolock) для каждой таблицы в объединении (если только это не производная таблица, в этом случае вы не можете использовать эту конкретную подсказку)

Самый простой ответ — простой вопрос: нужно ли вам, чтобы ваши результаты были повторяемыми?Если да, то NOLOCKS не подходит ни при каких обстоятельствах.

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

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top