Операторы SQL Server SELECT, вызывающие блокировку - PullRequest
16 голосов
/ 19 июня 2009

Мы используем базу данных SQL Server 2005 (без контроля версий строк) с огромным оператором select, и мы видим, что он блокирует выполнение других операторов (при использовании sp_who2). Я не осознавал, что операторы SELECT могут вызвать блокировку - могу ли я что-нибудь сделать, чтобы смягчить это?

Ответы [ 6 ]

29 голосов
/ 19 июня 2009

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

Если запрос неуправляем, то сначала следует рассмотреть уровень ИЗОЛЯЦИИ SNAPSHOT , во-вторых, вам следует рассмотреть возможность использования SNAPSHOTS БАЗЫ ДАННЫХ , а последний параметр должен быть DIRTY READS (и лучше изменить уровень изоляции вместо использования NOLOCK HINT). Обратите внимание, что грязные чтения, как ясно указывает название, будут возвращать противоречивые данные (например, ваш общий лист может быть несбалансированным).

14 голосов
/ 19 июня 2009

Из документации :

Блокировки

Shared (S) позволяют параллельным транзакциям считывать (SELECT) ресурс под пессимистическим контролем параллелизма. Для получения дополнительной информации см. Types of Concurrency Control. Никакие другие транзакции не могут изменять данные, пока на ресурсе существуют блокировки shared (S). Блокировки Shared (S) для ресурса снимаются, как только операция чтения завершается, если только уровень изоляции транзакции не установлен на повторяемое чтение или выше, или подсказка блокировки не используется для сохранения блокировок shared (S) на время транзакции.

A shared lock совместим с другой общей блокировкой или блокировкой обновления, но не с исключительной блокировкой.

Это означает, что ваши SELECT запросы будут блокировать UPDATE и INSERT запросы и наоборот.

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

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

Два SELECT запроса никогда не будут блокировать друг друга (если они не SELECT FOR UPDATE)

Вы можете включить SNAPSHOT уровень изоляции в своей базе данных и использовать его, но учтите, что он не предотвратит блокировку UPDATE запросов SELECT запросами (что, по-видимому, является вашим случаем).

Это, однако, предотвратит блокировку SELECT запросов UPDATE.

Также обратите внимание, что SQL Server, в отличие от Oracle, использует менеджер блокировок и сохраняет его в списке связанных в памяти.

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

2 голосов
/ 19 июня 2009

Чтобы выполнить грязное чтение, вы можете:

 using (new TransactionScope(TransactionScopeOption.Required, 
 new TransactionOptions { 
 IsolationLevel = System.Transactions.IsolationLevel.ReadUncommitted }))
 {
 //Your code here
 }

или

SelectCommand = "SELECT * FROM Table1 WITH (NOLOCK) INNER JOIN Table2 WITH (NOLOCK) ..."

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

0 голосов
/ 06 февраля 2019

Вы можете использовать WITH(READPAST) табличную подсказку. Это отличается от WITH(NOLOCK). Он получит данные до начала транзакции и никого не заблокирует. Представьте, что вы запустили оператор до начала транзакции.

SELECT * FROM table1  WITH (READPAST)
0 голосов
/ 19 июня 2009

Вы также можете получить тупики:

"тупики, включающие только одну таблицу" http://sqlblog.com/blogs/alexander_kuznetsov/archive/2009/01/01/reproducing-deadlocks-involving-only-one-table.aspx

или неверные результаты:

"Выбор в разделе ЧИТАТЬ СООТВЕТСТВУЕТ, а ПОВТОРЯЮЩИЙСЯ ЧТЕНИЕ может вернуть неверные результаты."

http://www2.sqlblog.com/blogs/alexander_kuznetsov/archive/2009/04/10/selects-under-read-committed-and-repeatable-read-may-return-incorrect-results.aspx

0 голосов
/ 19 июня 2009

Вы можете установить уровень транзакции для чтения непринятой

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...