Когда 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
как повторяемое чтение, могут быть добавлены любые новые строки, но любая параллельная транзакция не может удалить или обновить существующие строки