Вопрос

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

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

Решение

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

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

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

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

  Блокировки

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

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

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

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

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

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

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

Однако это предотвратит блокировку запросов SELECT с помощью UPDATE .

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

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

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

 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) ..."

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

Вы можете установить уровень транзакции читать незафиксированное

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

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

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

" При выборе значения READ COMMITTED и REPEATABLE READ могут возвращаться неверные результаты. "

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

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

SELECT * FROM table1  WITH (READPAST)
Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top