синтаксис для nolock в sql

Я видел операторы sql, использующие nolock и with(nolock), например -

select * from table1 nolock where column1 > 10

А ТАКЖЕ

select * from table1 with(nolock) where column1 > 10

Какое из приведенных утверждений верно и почему?


person seenasan    schedule 12.11.2009    source источник


Ответы (5)


Первый оператор ничего не блокирует, тогда как второй блокирует. Когда я только что проверил это на SQL Server 2005, в

select * from table1 nolock where column1 > 10 --INCORRECT

«nolock» стал в этом запросе псевдонимом table1.

select * from table1 with(nolock) where column1 > 10

выполняет желаемую функцию nolock. Скептически? В отдельном окне запустить

BEGIN TRANSACTION
UPDATE tabl1
 set SomeColumn = 'x' + SomeColumn

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

ROLLBACK

когда вы закончите.

person Philip Kelley    schedule 12.11.2009
comment
+1 За то, что уловил различие между (nolock) и nolock - точно в отношении псевдонима. Различие должно заключаться в использовании (nolock) против with (nolock), а не nolock против with (nolock), как показано в вопросе - хороший улов - person boydc7; 12.11.2009

Список устаревших функций находится по адресу Устаревшие функции ядра СУБД в SQL Server 2008. :

  • Указание NOLOCK или READUNCOMMITTED в предложении FROM инструкции UPDATE или DELETE.
  • Указание табличных подсказок без использования ключевого слова WITH.
  • Подсказка таблицы HOLDLOCK без круглых скобок
  • Использование пробела в качестве разделителя между табличными подсказками.
  • Косвенное применение таблицы намекает на вызов многооператорной функции с табличным значением (TVF) через представление.

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

При этом мои 2c по этому вопросу таковы:

  • И from table nolock, и from table with(nolock) неверны. Если вам нужны грязные чтения, используйте соответствующие уровни изоляции транзакций: set transaction isolation level read uncommitted . Таким образом, используемый уровень изоляции явно указывается и управляется одной «ручкой», в отличие от того, чтобы распространяться по источнику и подчиняться всем причудам табличных подсказок (косвенное применение через представления и TVF и т. д.).
  • Грязные чтения — это мерзость. В 99,99% случаев требуется снижение конкуренции, а не чтение незафиксированных данных. Конкуренция снижается за счет написания правильных запросов к хорошо разработанной схеме и, при необходимости, за счет развертывания изоляции моментальных снимков. Лучшее решение, которое почти всегда работает, за исключением нескольких крайних случаев, — это разрешить чтение зафиксированного снимка в базе данных и позволить движку творить чудеса:

    ALTER DATABASE MyDatabase SET ALLOW_SNAPSHOT_ISOLATION ON
    ALTER DATABASE MyDatabase SET READ_COMMITTED_SNAPSHOT ON

Затем удалите ВСЕ подсказки из выбора.

person Remus Rusanu    schedule 12.11.2009
comment
+1 за пару вещей, впервые я заметил устаревание nolock в FROM для обновления/удаления - очень приятно. Хотя я не полностью согласен с тем, что грязные чтения — это мерзость (есть несколько сценариев, когда их действительно имеет смысл использовать, даже вместо оптимистичного подхода к чтению), я согласен с тем, что ими злоупотребляют, неправильно понимают, и есть очень , очень мало сценариев, где это имеет смысл, и еще меньше случаев, когда его использование действительно понятно. - person boydc7; 13.11.2009
comment
Я согласен с тем, что грязные чтения имеют свою пользу, но, допустим, мне нравится использовать драматический эффект, чтобы подчеркнуть сообщение. - person Remus Rusanu; 13.11.2009
comment
NOLOCK был указан как функции, не поддерживаемые в следующей версии SQL Server для нескольких версий SQL Server. 2008, 2014 и 2016 годы. - person Marcel Wilson; 14.03.2017

Оба они технически правильны, однако не использовать ключевое слово WITH объявлено устаревшим начиная с SQL 2005, так что привыкайте использовать ключевое слово WITH — короткий ответ, используйте ключевое слово WITH.

person boydc7    schedule 12.11.2009
comment
Итак, with(nolock) в значительной степени стал новым синтаксисом с sql 2005, хотя сам по себе nolock все еще работает. это оно? - person seenasan; 12.11.2009
comment
да, все еще работает без with, но он устарел, то есть он не будет работать таким образом, скорее всего, в выпуске в какой-то момент в будущем (может быть следующий выпуск, может быть тот, что после этого, может быть 10 от сейчас)... - person boydc7; 12.11.2009
comment
также о вставке, обновление с (без блокировки) должно использоваться и там как норма программирования? - person seenasan; 12.11.2009
comment
Я бы не сказал, что использование табличных подсказок каким-либо образом будет/должно считаться нормой программирования - есть сценарии, в которых его можно/должно использовать, но это определенно не норма. Если вы спрашиваете, МОЖЕТЕ ли вы использовать их в операторе вставки/обновления, вы, безусловно, можете использовать их в предложениях FROM вставки/обновления, но вы не можете блокировать запись (т.е. фактическую вставку/обновление). - person boydc7; 12.11.2009
comment
Вставки и обновления (и удаления) будут игнорировать nolock — по крайней мере, в SQL Server. - person Philip Kelley; 12.11.2009
comment
Часть записи будет, да, отсюда утверждение, что вы не можете блокировать запись, но вы можете использовать их в части предложения FROM (т.е. вставить таблицуA (a,b,c) выбрать d,e,f из таблицыB с помощью (nolock)) - поиск/сканирование tableB будет учитывать отсутствие блокировки, а часть tableA - нет. - person boydc7; 12.11.2009
comment
Когда я сказал, что часть записи будет, да, я согласился с вами, Филип, что фактическая вставка/обновление/удаление будет игнорировать блокировку... сбиваю с толку после того, как я прочитал это - person boydc7; 12.11.2009
comment
Я понимаю - как-то тонко. Тем не менее, я думаю, что было бы очень плохой практикой сочетать модификации данных и отсутствие блокировки таким образом. - person Philip Kelley; 12.11.2009
comment
Я бы согласился для большинства случаев, абсолютно - person boydc7; 12.11.2009

Используйте «С (БЕЗ БЛОКИРОВКИ)».

person Rob Garrison    schedule 12.11.2009

Оба синтаксически правильны.

NOLOCK станет псевдонимом для table1.

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

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

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

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

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

Есть и другие побочные эффекты, которые приводят к потере увеличения скорости, которое вы надеялись получить в первую очередь.

Теперь вы знаете, никогда не используйте его снова.

person WonderWorker    schedule 05.02.2016