Вы можете легко проверить это сами.
Настройка
CREATE TABLE dbo.Customer
(
ID INT,
Balance INT,
Name CHAR(1)
)
INSERT INTO dbo.Customer
VALUES
(1 , 12 , 'A'),
(2 , 18 , 'B'),
(10, 100 , 'C');
Соединение 1 (транзакция остается открытой)
SET TRANSACTION ISOLATION LEVEL REPEATABLE READ
BEGIN TRAN
SELECT * FROM Customer
WHERE Balance BETWEEN 10 AND 20;
SELECT *
FROM sys.dm_tran_locks
WHERE request_session_id = @@SPID
Повторяемое чтение отличается от принятого чтения ( версия блокировки), поскольку она сохраняет блокировки S
для строк, соответствующих условию WHERE
, а не освобождает их, как только читается строка.
Запрос к sys.dm_tran_locks
показывает, что он содержит две блокировки RID сопоставление двух возвращенных строк.
Вывод флага трассировки 1200 для вышеуказанного
показывает, что он получает три блокировки строки S
и удерживает блокировки в строках, которые соответствуют критериям фильтра
Process 64 acquiring IS lock on OBJECT: 5:917578307:0 (class bit2000000 ref1) result: OK
Process 64 acquiring IS lock on PAGE: 5:1:256 (class bit2000000 ref0) result: OK
Process 64 acquiring S lock on RID: 5:1:256:0 (class bit2000000 ref0) result: OK
Process 64 acquiring S lock on RID: 5:1:256:1 (class bit2000000 ref0) result: OK
Process 64 acquiring S lock on RID: 5:1:256:2 (class bit2000000 ref0) result: OK
Process 64 releasing lock on RID: 5:1:256:2
Если вы попытаетесь подключиться к другому
DELETE FROM Customer WHERE Balance = 12;
, вы увидите, что это заблокировано блокировкой строки, удерживаемой исходной транзакцией. Обратите внимание, что это в конечном итоге завершится успешно, когда исходная транзакция фиксирует и снимает свои блокировки.
Отмените эту попытку и попробуйте
UPDATE Customer SET Balance = 14 WHERE Balance = 100;
, это сразу же удастся. Исходная транзакция никогда не сохраняла блокировку S
в этой строке, так как, несмотря на то, что она была прочитана (из-за отсутствия индекса в Balance
), она не соответствовала условию WHERE
, и блокировка была снята согласно releasing lock
вывод выше.