Держать эксклюзивную блокировку для запроса - PullRequest
0 голосов
/ 17 марта 2020

SQL Сервер: как удерживать монопольную блокировку для запроса выбора? Для mysql,

select * from Employee e
where e.id=123
for update

Другая параллельная транзакция не может прочитать или записать выбранную строку.

Как добиться того же для SQL сервера?

SELECT *
FROM   Employee e
WITH   (HOLDLOCK, ROWLOCK)
WHERE  e.id = 123;

Для (HOLDLOCK, ROWLOCK) удерживает ли он READ LOCK в выбранной строке? С READ LOCK другая транзакция все еще может прочитать заблокированную строку, верно?

Ответы [ 2 ]

0 голосов
/ 18 марта 2020

Вы должны указать XLOCK-подсказку в своем выражении для достижения желаемого поведения.

Другая параллельная транзакция не может прочитать или записать выбранную строку.

SELECT *
FROM Employee e
WITH (XLOCK)
WHERE e.id = 123;

Теперь я хочу описать, почему HOLDLOCK и ROWLOCK не помогут.

HOLDLOCK сообщит SqlServer о необходимости удерживать S-блокировки (общие блокировки) до завершения транзакции. S-блокировка предотвращает одновременную запись во время чтения. Но это позволяет читать данные одновременно. Вот почему это называется «общий». По умолчанию общие блокировки действуют так долго, как это предусмотрено текущим уровнем изоляции транзакции. Для уровня изоляции зафиксированного чтения (который используется по умолчанию) общая блокировка будет снята после того, как данные полностью прочитаны. Это означает, что блокировки на уровне строки снимаются сразу после чтения строки, блокировки на уровне страницы снимаются после того, как все данные на странице были прочитаны, а блокировки на уровне таблицы снимаются после завершения оператора. Но HOLDLOCK принудительно освобождает общие блокировки в конце транзакции. Таким образом, когда вы устанавливаете HOLDLOCK, общие блокировки оператора вынуждены жить дольше, как если бы они выполнялись в транзакции с повторяемым уровнем изоляции чтения.

XLOCK работает так же, как HOLDLOCK, с одним отличием: X-блокировки (исключая используются блокировки.

UPDLOCK вынуждает SqlServer использовать U-блокировки (обновления блокировок) вместо S-блокировок без каких-либо других отличий с подсказкой HOLDLOCK. U-блокировка - это определенный тип блокировки c для операторов чтения, за которыми следуют любые записи в транзакции, что потенциально может вызвать взаимоблокировки. Таким образом, вы используете UPDLOCK, когда хотите ограничить чтение одних и тех же данных во время одновременных транзакций с целью обновления.

ROWLOCK говорит SqlServer держать блокировки на уровне строки, даже если предполагается блокировка на уровне страницы или таблицы использоваться. По сути, вам не нужно указывать ROWLOCK, если вы не уверены, что делаете, потому что вы можете усложнить выполнение операторов.

0 голосов
/ 17 марта 2020

С добавлением эксклюзивной блокировки (xlock) или блокировки обновления (updlock) любой другой оператор выбора будет заблокирован на время транзакции. Будет ли заблокирована только строка (или нет), зависит от того, как осуществляется доступ к строке: если выполняется сканирование таблицы, вся таблица блокируется исключительно.

begin transaction
select *
from Employee with(xlock /*or updlock*/, holdlock, rowlock /*not assured*/)
where id = 123

--check the locks
exec sp_lock
--rollback transaction
...