Использование уровня изоляции MySQL для Repeatable Read.
Для данной таблицы test
с неиндексированным столбцом quantity
:
id | quantity
--------------------
1 | 10
2 | 20
3 | 30
Tx1 выполняется 1-м, обратите внимание, что он не зафиксированеще означает, что все полученные блокировки еще не сняты.
Tx1:
START TRANSACTION;
DELETE FROM test WHERE quantity=10;
Теперь выполняется Tx2
Tx2:
START TRANSACTION;
INSERT INTO test(quantity) VALUES (40);
COMMIT;
Для Tx2 я получаю следующий результат:
Lock wait timeout exceeded; try restarting transaction
Я понимаю, что, поскольку столбец quantity
не проиндексирован, оператор delete
выполняет полное сканирование таблицы, блокирует все строки (ненезависимо от того, соответствует условие where
или нет), а также применяет блокировки пробелов перед каждой и после последней индексной записи в кластеризованном индексе, что приводит к полностью блокированной таблице, следовательно, оператор insert
из tx2 не может получить блокировку для строки, которая будетвставлен.
Из MySQL руководство (для уровня изоляции Repeatable Read):
Для уникального индекса с уникальным условием поиска,InnoDB блокирует только найденную запись индекса, а не пробел доe it.
Для других условий поиска InnoDB блокирует сканированный диапазон индекса, используя блокировки пробелов или блокировки следующего ключа, чтобы блокировать вставки другими сеансами в промежутки, охватываемые диапазоном (этоиспользуется в моем случае).
Принимая во внимание, что блокировка на любом данном уровне изоляции применяется для предотвращения phenomenas
Я немного запутался в том, чтопричина блокирования всей таблицы в этом случае, я имею в виду, какой тип phenomena
предотвращается блокированием всей таблицы в этом случае?