以下示例说明了锁定请求如何导致死锁。该示例涉及两个客户端,A 和 B。
首先,客户端 A 创建一个包含一行的表,然后开始一个事务。在事务中,A 通过在共享模式下查询该行来获得对该行的锁定:
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 FOR SHARE;+------+| i |+------+| 1 |+------+接下来,客户端 B 开始一个事务并尝试从表中删除该行:
mysql> START TRANSACTION;Query OK, 0 rows affected (0.00 sec)mysql> DELETE FROM t WHERE i = 1;删除操作需要排他锁。无法授予该行共享锁,因为它与客户端 A 持有的锁不兼容,因此请求进入行锁请求队列并堵塞客户端 B 。
最后,客户端 A 还尝试从表中删除该行:
mysql> DELETE FROM t WHERE i = 1;这里发生死锁是因为客户端 A 需要一个排他锁来删除行。但是,无法授予该锁定请求,因为客户端 B 已经有一个排他锁定请求,并且正在等待客户端 A 释放其共享锁定。A持有的共享锁也不能升级为排他锁,因为B先申请排他锁。结果, InnoDB为其中一个客户端生成错误并释放其锁定。客户端返回此错误:
ERROR 1213 (40001): Deadlock found when trying to get lock;try restarting transaction此时,可以授予其他客户端的锁定请求,并从表中删除该行。
| 留言与评论(共有 0 条评论) “” |