Documentation Home

14.7.5.1 InnoDB 死锁示例

以下示例说明了当锁定请求导致死锁时错误是如何发生的。该示例涉及两个客户端 A 和 B。

首先,客户端 A 创建一个包含一行的表,然后开始一个事务。在事务中,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 |
+------+

接下来,客户端 B 开始一个事务并尝试从表中删除该行:

mysql> START TRANSACTION;
Query OK, 0 rows affected (0.00 sec)

mysql> DELETE FROM t WHERE i = 1;

删除操作需要X锁。锁不能被授予,因为它与 S客户端 A 持有的锁不兼容,所以请求进入行和客户端 B 块的锁请求队列。

最后,客户端 A 还尝试从表中删除该行:

mysql> DELETE FROM t WHERE i = 1;

X这里会出现死锁,因为客户端A删除行 需要 锁。但是,无法授予该锁定请求,因为客户端 B 已经有一个X锁定请求并正在等待客户端 A 释放其S锁定。也不能 因为 B 事先请求锁而将SA 持有的锁升级 为锁。结果, 为其中一个客户端生成错误并释放其锁。客户端返回此错误: XXInnoDB

ERROR 1213 (40001): Deadlock found when trying to get lock;
try restarting transaction

此时,可以授予其他客户端的锁定请求,并从表中删除该行。