Когда UPDLOCK будет выпущен на сервере SQL?

Недавно я прошел через подсказки и блокировки в SQL-сервере. В то время как Google об этой теме, я прочитал один блог, где был написан какой-то запрос, который я не собираюсь понимать. Вот

Состояния BOL: используйте блокировки обновления вместо общих блокировок при чтении таблицы и удерживайте блокировки до конца оператора или транзакции. У меня есть некоторые проблемы с переводом. Означает ли это, что блокировки обновления снимаются после выполнения оператора SELECT, если только оператор SELECT не находится внутри транзакции?

Другими словами, верны ли мои предположения в следующих двух сценариях?

Сценарий 1: нет транзакции

SELECT something FROM table WITH (UPDLOCK)

/* update locks released */

Сценарий 2: с транзакцией

BEGIN TRANSACTION 
SELECT something FROM table WITH (UPDLOCK)

/* some code, including an UPDATE */
COMMIT TRANSACTION

/* update locks released */

Пример для сценария 2 (упоминается для блога stackru)

BEGIN TRAN

SELECT Id FROM Table1 WITH (UPDLOCK)
WHERE AlertDate IS NULL;

UPDATE Table1 SET AlertDate = getutcdate() 
WHERE AlertDate IS NULL;

COMMIT TRAN 

Пожалуйста, помогите понять вышеупомянутый запрос.

Мой второй вопрос: после выполнения оператора select одновременно UPDLOCK освободиться или нет?

2 ответа

Решение

Ваше предположение в сценарии 2 верно.

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

BEGIN TRAN
    -- execute sp_lock in second session - no locks yet
    SELECT Id FROM Table1 WITH (UPDLOCK) WHERE AlertDate IS NULL;
    -- execute sp_lock in second session - update locks present
    UPDATE Table1 SET AlertDate = getutcdate() WHERE AlertDate IS NULL;
    -- execute sp_lock in second session - update (U) locks are replace by exclusive locks (X) for all row(s) returned by SELECT and modified by the UPDATE (Lock Conversion).
    -- Update locks (U) continue to be held for any row(s) returned by the SELECT but not modified by the UPDATE
    -- exclusive locks (X) are also held on all rows not returned by SELECT but modified by UPDATE. Internally, lock conversion still occurs, because UPDATE statements must read and write.
COMMIT TRAN 

    -- sp_lock in second session - all locks gone.

Что касается того, что происходит в сценарии 1, все операторы T-SQL существуют либо в неявной, либо в явной транзакции. Senario 1 неявно:

BEGIN TRAN
     SELECT something FROM table WITH (UPDLOCK)
     -- execute sp_lock in second session - update locks (U) will be present
     COMMIT TRAN;
     -- execute sp_lock in second session - update locks are gone.

Означает ли это, что блокировки обновления снимаются после выполнения оператора SELECT, если только оператор SELECT не находится внутри транзакции?

Блокировки будут сняты, как только будет прочитана строка.. но удержание блокировки будет U блокировка, поэтому любая параллельная транзакция, пытающаяся изменить это, должна будет ждать

если вы укажете выше select в транзакции, блокировки будут сняты только тогда, когда транзакция будет зафиксирована, поэтому любые параллельные транзакции, получающие блокировки, несовместимы с U замок придется ждать

begin tran
select * from t1 with (updlock)

для второго сценария ниже

BEGIN TRANSACTION 
SELECT something FROM table WITH (UPDLOCK)

/* some code, including an UPDATE */
COMMIT TRANSACTION

Представьте, если ваш запрос на выборку вернул 100 строк, все будут использовать U заблокировать и представить, что обновление в той же транзакции затрагивает 2 строки, две строки будут преобразованы в x блокирует. Так что теперь ваш запрос будет иметь 98 u замки и 2 xблокируется до совершения транзакции

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

Другие вопросы по тегам