MySQL官方文档14.5.5.1 InnoDB死锁示例

原文地址:https://dev.mysql.com/doc/refman/5.7/en/innodb-deadlock-example.html

14.5.5.1 InnoDB死锁示例

以下示例说明了锁请求如何发生错误会导致死锁时。这个例子涉及两个客户端,A和B。
首先,客户端A创建一个包含一行的表,然后开始一个事务。在事务中,A通过在共享模式下select来获得行上的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锁。该锁不能被授予,因为它与客户端A持有的S锁不兼容,所以该请求会进入行的锁请求队列并且客户端B阻塞。

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

mysql> DELETE FROM t WHERE i = 1;
ERROR 1213 (40001): Deadlock found when trying to get lock;
try restarting transaction

死锁发生在这里,因为客户端A需要X锁来删除该行。但是,该锁请求不能被授予,因为客户端B已经有一个X锁请求,并且正在等待客户端A释放其S锁。由于B先前请求X锁,因此A持有的S锁也不能升级为X锁。结果,InnoDB为其中一个客户端生成一个错误并释放它的锁。客户返回这个错误:

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

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

猜你喜欢

转载自blog.csdn.net/heroqiang/article/details/80624520