Общие сведения о SQL Server LOCKS по запросам SELECT

Мне интересно, какая польза для использования SELECT WITH (NOLOCK) в таблице, если только другие запросы, влияющие на эту таблицу, являются SELECT запросами.

Как это обрабатывается SQL Server? Будет ли запрос SELECT блокировать другой запрос SELECT?

Я использую SQL Server 2012 и Linq-to-SQL DataContext.

(EDIT)

О производительности:

  • Будет ли второй SELECT ждать окончания 1-го SELECT, если использовать заблокированный SELECT?
  • В сравнении с SELECT WITH (NOLOCK)?

Спасибо.

Ответ 1

A SELECT в SQL Server поместит общую блокировку в строку таблицы, а второй SELECT также потребует общую блокировку, и они совместимы друг с другом.

Поэтому no-one SELECT не может заблокировать другой SELECT.

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

Без подсказки запроса SELECT может быть заблокирован чтение таблицы текущим оператором INSERT (или UPDATE), который устанавливает исключительную блокировку для строк (или, возможно, целую таблицу), до тех пор, пока эта операция не будет выполнена (или откат).

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

Еще один подсказку подсказки, которая может быть полезна - WITH (READPAST). Это дает команду SELECT просто пропустить любые строки, которые он пытается прочитать, и которые заблокированы исключительно. SELECT не будет блокироваться, и он не будет считывать "грязные" данные, не переданные, но может пропустить некоторые строки, например. не показывать все ваши строки в таблице.

Ответ 2

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

По умолчанию для выбора (чтения) используется общая блокировка.
Заблокированные (S) блокировки позволяют параллельным транзакциям читать (SELECT) ресурс.
Общая блокировка не влияет на другие варианты (1 или 1000).

Различие заключается в том, как обновлять или вставлять эффекты nolock или shared lock.

Никакие другие транзакции не могут изменять данные, а общие (S) блокировки существуют на ресурсе.

Общая блокировка блокирует обновление!
Но nolock не блокирует обновление.

Это может иметь огромное влияние на производительность обновлений. Это также влияет на вставки.

Грязное чтение (nolock) просто звучит грязно. Вы никогда не получите частичные данные. Если обновление меняет Джона на Салли, вы никогда не получите Jolly.

Я использую общие блокировки для concurrency. Данные устаревают, как только они считываются. Чтение Джона, которое меняется на Салли в следующую миллисекунду, - это устаревшие данные. Чтение Салли, которая откатывается назад, следующая миллисекунда - это устаревшие данные. Это на миллисекундах. У меня есть dataloader, который занимает 20 часов для запуска, если пользователи используют общие блокировки и 4 часа для запуска - пользователи не блокируют. Общие блокировки в этом случае заставляют данные хранить 16 часов.

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

Ответ 3

Мне нужно добавить важный комментарий. Все упоминают, что NOLOCK читает только грязные данные. Это неточно. Также возможно, что вы получите одну и ту же строку дважды или целую строку, пропущенную во время чтения. Причина в том, что вы можете запросить некоторые данные в одно и то же время, когда SQL Server перебалансирует b-дерево.

Проверить другие темы

fooobar.com/questions/14598/...

http://www.sqlmag.com/article/sql-server/quaere-verum-clustered-index-scans-part-iii.aspx)

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

Ответ 4

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

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

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

Нам пришлось добавить "NO LOCK" к нашему оператору SELECT, потому что это был огромный SELECT на таблице, который многократно используется многими пользователями одновременно, и у нас всегда были LOCKS.

Я не знаю, достаточно ли моего примера? Это пример реальной жизни.

Ответ 5

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

В Википедии есть полезная статья: Википедия: Изоляция (системы баз данных)

Он также подробно обсуждается в других статьях stackoverflow.

Ответ 6

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

например - позволяет сказать, что транзакция вставляет 1000 строк, а затем терпит неудачу.

когда вы выберете - вы получите 1000 строк.