14.7.5.1 Пример тупиковой ситуации в InnoDB
Следующий пример демонстрирует, как может произойти ошибка, когда запрос на блокировку приводит к тупиковой ситуации. В примере участвуют два клиента, А и Б.
Сначала клиент А создает таблицу, содержащую одну строку, а затем начинает транзакцию. В рамках транзакции А получает 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 |
+------+
Далее, клиент Б начинает транзакцию и пытается удалить строку из таблицы:
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;
Здесь возникает тупиковая ситуация, потому что клиенту А нужна X блокировка для удаления строки. Однако этот запрос на блокировку не может быть удовлетворен, потому что клиент Б уже имеет запрос на X блокировку и ожидает, пока клиент А не освободит свою S блокировку. Также S блокировка, удерживаемая А, не может быть повышена до X блокировки из-за предыдущего запроса Б на X блокировку. В результате InnoDB генерирует ошибку для одного из клиентов и освобождает его блокировки. Клиент возвращает эту ошибку:
ERROR 1213 (40001): Deadlock found when trying to get lock;
try restarting transaction
В этот момент запрос на блокировку для другого клиента может быть удовлетворен, и он удаляет строку из таблицы.
© 2025 Oracle
Licensed under the GPLv2 License.