2012-08-06 4 views
7

У меня есть сложный запрос выбора и огромная таблица.SQL Server - блокировка [SELECT] [UPDATE]?

Я бег это select заявления, тем временем Update заявления приходит и пытается обновления таблицы.

ИМХО - обновление требует блокировки эксклюзивного - поэтому оператор обновления придется ждать пока команда выбора закончена.

  1. Я прав?

  2. , что я могу сделать для того, чтобы: выполнить сложную select, и также впустить update команду Run (в настоящее время я не заботиться о грязных данных)

+1

Какой уровень изоляции транзакций вы говорите? – Oded

+0

@Oded По умолчанию - я считаю, что он читается. –

+3

* «В настоящее время я не забочусь о грязных данных» *: будьте осторожны [что вы хотите] (http://blogs.msdn.com/b/sqlcat/archive/2007/02/01/previously-committed- строки-может быть пропущенным-если-NOLOCK-подсказка-это-used.aspx). –

ответ

13

Да - градус.

Как долго SELECT держит на общий замок находится в зависимости от уровня изоляции транзакции:

  • READ UNCOMMITTED - не разделяемая блокировка приобретаемого у всех - UPDATE не заблокирован
  • READ COMMITTED - общий блокировка производится только на время считывания данных - UPDATE может быть заблокирован в течение очень короткого периода времени
  • REPEATABLE READ и SERIALIZABLE - общий замок приобретен и удерживается до л конец сделки - UPDATE блокируется, пока SELECT транзакция не заканчивается

Технически UPDATE заявление первым получает UPDATE замка - который совместит с общим замком (как это используется SELECT) - в течение всего срока времени, пока он считывает текущие значения строк для обновления.

После этого замок Update перейдет в эксклюзивную блокировку для записи новых данных в таблицу.

+0

'инструкция UPDATE сначала получает блокировку UPDATE, которая совместима с общей блокировкой' я не понимаю marc. обновление ждет выбора, чтобы закончить? –

+1

@RoyiNamir: обновление может получить блокировку «Обновить» (для чтения «старых» данных), в то время как другой процесс все еще читает эту же строку и имеет «разделяемую» блокировку в этой строке. Обновление не сможет перейти к эксклюзивной блокировке (для записи «новых» данных), однако, пока эта 'shared'-блокировка все еще на месте, поэтому ей придется подождать там ... –

5

Когда вы выполняете оба утверждения одновременно (SELECT и UPDATE), фактическое поведение будет в основном случайным. Это происходит потому, что ни одна из операций не является мгновенной. Чтобы упростить, рассмотрите таблицу в списке и SELECT перебирает этот список, глядя на одну строку за раз. UPDATE также пытается обновить одну или несколько строк. Когда UPDATE пытается обновить строку позади SELECT, тогда ничего не происходит (без блокировки), потому что SELECT уже прошел мимо точки UPDATE. Если UPDATE пытается обновить строку, в которой SELECT ищет прямо сейчас, то UPDATE придется ждать, пока SELECT будет двигаться, что произойдет очень очень быстро, и UPDATE разблокирует и преуспеет, , а SELECT продвигается вперед. Но если UPDATE обновляет строку вперед из SELECT, то обновление будет успешным и, позже, SELECT в конечном итоге достигнет именно этой строки и остановится, заблокирован.Теперь SELECT должен подождать , пока транзакция, которая сделала UPDATE, не зафиксировала.

Это упрощенная история. Реальная жизнь намного сложнее. SELECT может иметь несколько точек чтения (параллельные планы). И SELECT, и UPDATE подлежат выбору пути доступа, то есть используют один или несколько вторичных индексов для поиска строк. Комплексные запросы могут содержать операторы, которые вызывают множественный поиск в таблице (например, объединения). И SELECT, и UPDATE могут выполнять поиск по закладкам для извлечения данных BLOB, что значительно изменяет поведение блокировки. Оценка мощности может привести к тому, что SELECT будет работать в режиме блокировки с высокой степенью детализации (например, на уровне таблицы Shared lock). UPDATE может инициировать эскалацию блокировки, и эскалация может завершиться неудачей или преуспеть. Choosing different access paths can lead to deadlock. False lock contention can occur due to hash collisions. В этом есть всего несколько переменных. И я даже не упоминал более высокие уровни изоляции (повторяемое чтение, сериализация).

Возможно, вы должны использовать изоляцию SNAPSHOT и перестать беспокоиться об этой проблеме?

+0

Если вы предлагаете перейти к 'SNAPSHOT' - просто убедитесь, что' TempDB' правильно настроен! (местоположение и количество файлов данных, параметры калибровки и т. д.) –

+1

Да, повторяемая и сериализуемая причина, которую необходимо сохранить для области транзакции. Serializable также добавляет блокировки диапазона. Все это добавляет сложности. –

+1

@marc_s: ссылка на тему MSDN охватывает [Использование ресурса для управления версиями строк] (http://msdn.microsoft.com/en-us/library/ms175492 (v = sql.105)). Я предпочитаю не пугать пользователей, так как я считаю, что преимущества SNAPSHOT намного превышают его стоимость. –

Смежные вопросы