MySQL 8.0 新特性之死锁检测控制

在 MySQL 中,如果两个不同的事务在执行时,互相持有了对方所需的锁,此时由于它们都在等待某个资源,永远不会释放自己获得的锁,因此就会产生死锁(deadlock)。

以下是一个产生死锁的示例。首先,在客户端 A 中创建一个表 t,它只有一行数据。然后开始一个事务,并且通过共享查询模式获取该行数据上的 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 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 已经获得了一个 S 锁,客户端 B 的锁请求需要进入锁的等待队列,因此客户端 B 被阻塞。

最后,在客户端 A 中也尝试删除该行数据:

mysql> DELETE FROM t WHERE i = 1;
Query OK, 1 row affected (0.00 sec)



同时,在客户端 B 返回以下错误信息:

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



此时产生了死锁,因为客户端 A 需要获得一个 X 锁才能删除该行数据。然而,客户端 A 无法获得该锁,因为客户端 B 已经请求了一个 X 锁,并且等待客户端 A 释放该数据行上的 S 锁。客户端 A 上的 S 锁也无法升级为 X 锁,因为客户端 B 的 X 锁请求优先级更高。结果就是,InnoDB 将会在某个客户端产生错误,并且释放它所获取的锁。

至此,另一个客户端(A)能够获得请求的锁,并且删除该数据行。

通过以上示例可以看出,当启用了死锁检测时(默认设置),InnoDB 自动执行事务的死锁检测,并且回滚一个或多个事务以解决死锁。InnoDB 尝试回滚更小的事务,事务的大小由它所插入、更新或者删除的数据行数决定。

更多请见:http://www.mark-to-win.com/tutorial/51597.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值