Какова теория, когда запрос DELETE или UPDATE входит в уровень изоляции Repeatable Read? - PullRequest
0 голосов
/ 18 апреля 2020

В Repeatable Read Isolation Level он не запрещает другим транзакциям вставлять новые строки в таблицы, которые были выбраны в текущей транзакции. Я хочу знать теорию, лежащую в основе запроса DELETE или UPDATE? Рассмотрим следующий пример, который я пытаюсь решить.

Предполагается использование системы управления реляционными базами данных (RDBMS) и строгого подхода двухфазной блокировки для контроля параллелизма.

ID  Balance Name
1   12      A
2   18      B
10  100     C

На следующей временной диаграмме показано выполнение двух одновременных транзакций на основе приведенной выше таблицы Customer , T1 и T2, обе из которых выполняются на уровне изоляции транзакции REPEATABLE_READ .

            T1                                  T2
SELECT * FROM Customer              |
WHERE Balance BETWEEN 10 AND 20;    |
                                    |       **QUERY X** 
                                    |       COMMIT; "
SELECT * FROM Customer              |
WHERE Balance BETWEEN 10 AND 20;    |

Будет ли проявляться аномалия Фантома, если вместо запроса INSERT один из следующих операторов SQL будет заменен на QUERY X на T2? Обосновать ответ.

  1. ОБНОВЛЕНИЕ Клиентский набор Баланс = 14 ГДЕ Баланс = 100;
  2. УДАЛИТЬ ОТ клиента, ГДЕ Баланс = 12;

Я новичок в СУБД, поэтому я очень благодарен за добрые объяснения, которые помогают мне лучше понять эти проблемы.

1 Ответ

1 голос
/ 18 апреля 2020

Вы можете легко проверить это сами.

Настройка

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 вывод выше.

...