Spec-Zone .ru
спецификации, руководства, описания, API

14.2.3.2. InnoDB Режимы блокировки

InnoDB блокировка стандарта реализаций на уровне строки, где есть два типа блокировок:

Если транзакция T1 содержит совместно используемое (S) соедините строку r, тогда запросы от некоторой отличной транзакции T2 для блокировки на строке r обрабатываются следующим образом:

Если транзакция T1 содержит монопольное (X) соедините строку r, запрос от некоторой отличной транзакции T2 для блокировки любого типа на r не может быть сразу предоставлен. Вместо этого транзакция T2 должен ожидать транзакции T1 выпускать его блокировку на строке r.

Дополнительно, InnoDB поддерживает многократную блокировку гранулярности, которая разрешает, чтобы сосуществование записи заблокировало и соединило все таблицы. Чтобы сделать блокировку на многократных уровнях гранулярности, практические, дополнительные типы блокировок, названных блокировками намерения, используются. Блокировки намерения являются блокировками таблицы в InnoDB это указывает, какого типа блокировки (совместно используемый или монопольный) транзакция потребует позже для строки в той таблице. Есть два типа блокировок намерения, используемых в InnoDB (примите ту транзакцию T запросил блокировку обозначенного типа на таблице t):

Например, SELECT ... LOCK IN SHARE MODE наборы IS блокировка и SELECT ... FOR UPDATE наборы IX блокировка.

Протокол блокировки намерения следующие:

Эти правила могут быть удобно получены в итоге посредством следующей матрицы соответствия типов блокировки.

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.