#### 15.7.5.1 InnoDB 死锁示例

[](<>)[](<>)

以下示例说明了当锁定请求导致死锁时如何发生错误。该示例涉及两个客户端，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;
```

删除操作需要`X`锁。无法授予锁，因为它与`小号`客户端 A 持有的锁，因此请求进入行的锁请求队列和客户端 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 释放其`小号`锁。也不能`小号`A持有的锁升级为`X`由于 B 之前的请求而锁定`X`锁。因此，`InnoDB`为其中一个客户端生成错误并释放其锁定。客户端返回此错误：

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

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