Spec-Zone .ru
спецификации, руководства, описания, API
|
InnoDB
блокировка стандарта реализаций на уровне строки, где
есть два типа блокировок:
Совместно
используемое (S
) заблокируйте разрешает транзакцию,
которая содержит блокировку, чтобы считать строку.
Монопольное
(X
) заблокируйте разрешает транзакцию, которая содержит
блокировку, чтобы обновить или удалить строку.
Если транзакция T1
содержит совместно используемое (S
) соедините строку r
, тогда запросы от
некоторой отличной транзакции T2
для блокировки на строке r
обрабатываются следующим образом:
Запрос T2
для S
блокировку можно сразу предоставить. В результате оба T1
и T2
содержите S
соединиться r
.
Запрос T2
для X
блокировку нельзя сразу предоставить.
Если транзакция T1
содержит монопольное (X
) соедините строку r
, запрос от
некоторой отличной транзакции T2
для блокировки любого типа на r
не может быть сразу предоставлен. Вместо этого транзакция T2
должен ожидать транзакции T1
выпускать его
блокировку на строке r
.
Дополнительно, InnoDB
поддерживает многократную
блокировку гранулярности, которая разрешает, чтобы сосуществование записи заблокировало и соединило
все таблицы. Чтобы сделать блокировку на многократных уровнях гранулярности, практические, дополнительные типы
блокировок, названных блокировками
намерения, используются. Блокировки намерения являются блокировками таблицы в InnoDB
это указывает, какого типа блокировки (совместно используемый или монопольный) транзакция потребует позже для
строки в той таблице. Есть два типа блокировок намерения, используемых в InnoDB
(примите ту транзакцию T
запросил блокировку обозначенного типа на таблице t
):
Совместно использованное намерение (IS
): Транзакция T
намеревается
установить S
соединяет отдельные строки в таблице t
.
Монопольное намерение (IX
): Транзакция T
намеревается
установить X
соединяет те строки.
Например, SELECT
... LOCK IN SHARE MODE
наборы IS
блокировка и SELECT ...
FOR UPDATE
наборы IX
блокировка.
Протокол блокировки намерения следующие:
Прежде, чем транзакция может получить S
соедините строку в таблице t
, это должно сначала получить IS
или более сильная блокировка на t
.
Прежде, чем транзакция может получить X
соедините строку, она должна сначала получить IX
соединиться
t
.
Эти правила могут быть удобно получены в итоге посредством следующей матрицы соответствия типов блокировки.
X |
IX |
S |
IS |
|
---|---|---|---|---|
X |
Конфликт | Конфликт | Конфликт | Конфликт |
IX |
Конфликт | Совместимый | Конфликт | Совместимый |
S |
Конфликт | Конфликт | Совместимый | Совместимый |
IS |
Конфликт | Совместимый | Совместимый | Совместимый |
Блокировку предоставляют транзакции запроса, если это является совместимым с существующими блокировками, но не, если это конфликтует с существующими блокировками. Транзакция ожидает, пока конфликтная существующая блокировка не выпускается. Если бы запрос блокировки конфликтует с существующей блокировкой и не может быть предоставлен, потому что он вызвал бы мертвую блокировку, ошибка происходит.
Таким образом блокировки намерения не блокируют ничего кроме полных табличных запросов (например, LOCK TABLES ... WRITE
). Основная цель IX
и
IS
блокировки должны показать, что кто-то блокирует строку, или
собирается заблокировать строку в таблице.
Следующий пример иллюстрирует, как ошибка может произойти, когда запрос блокировки вызвал бы мертвую блокировку. Пример включает два клиента, A и B.
Во-первых, клиент А составляет таблицу, содержащую одну строку, и затем начинает транзакцию. В пределах
транзакции A получает S
соедините строку, выбирая это в режиме доли:
mysql>CREATE TABLE t (i INT) ENGINE = InnoDB;
Query OK, 0 rows affected (1.07 sec)mysql>INSERT INTO t (i) VALUES(1);
Query OK, 1 row affected (0.09 sec)mysql>START TRANSACTION;
Query OK, 0 rows affected (0.00 sec)mysql>SELECT * FROM t WHERE i = 1 LOCK IN SHARE MODE;
+------+| i |+------+| 1 |+------+1 row in set (0.10 sec)
Затем, клиент Б начинает транзакцию и пытается удалить строку из таблицы:
mysql>START TRANSACTION;
Query OK, 0 rows affected (0.00 sec)mysql>DELETE FROM t WHERE i = 1;
Удалить работа требует X
блокировка. Блокировку нельзя предоставить,
потому что это является несовместимым с S
блокировка, которую содержит
тот клиент А, таким образом, запрос идет на очередь запросов блокировки на блоки клиента Б и строку.
Наконец, клиент также пытается удалить строку из таблицы:
mysql> DELETE FROM t WHERE i = 1;
ERROR 1213 (40001): Deadlock found when trying to get lock;try restarting transaction
Мертвая блокировка происходит здесь потому что клиент потребности X
блокировка, чтобы удалить строку. Однако, тот запрос блокировки нельзя предоставить, потому что у клиента Б уже
есть запрос на X
заблокируйте и ожидает клиента, чтобы выпустить S
блокировка. Ни может S
блокировка, сохраненная A быть обновленным до X
блокировка из-за
предшествующего запроса B для X
блокировка. В результате InnoDB
генерирует ошибку для одного из клиентов и выпускает ее блокировки. Клиент
возвращает эту ошибку:
ERROR 1213 (40001): Deadlock found when trying to get lock;try restarting transaction
В той точке можно предоставить запрос блокировки на другой клиент, и это удаляет строку из таблицы.
Если LATEST DETECTED DEADLOCK
раздел вывода Монитора InnoDB включает
утверждение сообщения, "СЛИШКОМ ГЛУБОКИЙ ИЛИ ДОЛГИЙ ПОИСК В ТАБЛИЦЕ БЛОКИРОВКИ ОЖИДАЕТ - ГРАФИКА, МЫ будем ОТКАТЫВАТЬ СЛЕДУЮЩУЮ ТРАНЗАКЦИЮ,"
указывает это, что число транзакций на ожидании - для списка достигло предела 200, который определяется
LOCK_MAX_DEPTH_IN_DEADLOCK_CHECK
. Ожидание - для списка, который превышает 200
транзакций, обрабатывается как мертвая блокировка и транзакция, пытающаяся проверять, что ожидание - для
списка откатывается.
Та же самая ошибка может также произойти, если поток блокировки должен смотреть больше чем на 1 000
000 блокировок, принадлежавших транзакциям на ожидании - для списка. Предел 1 000 000 блокировок
определяется LOCK_MAX_N_STEPS_IN_DEADLOCK_CHECK
.