[笔记]MySQL 插入导致死锁

"本文通过一个具体的场景展示了在MySQL中如何引发死锁。在REPEATABLE-READ隔离级别下,两个并发事务尝试插入数据,由于彼此等待对方释放锁导致死锁。通过SHOW ENGINE InnoDB STATUSG可以查看死锁详情。分析了事务1和事务2的执行顺序,解释了死锁产生的原因,并提供了相关参考资料进一步理解MySQL的插入锁机制。"

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

线上遇到的 MySQL 插入导致死锁,问题排查.

场景复现

MySQL 版本: 5.7.36
数据库存储引擎: InnoDB
事务隔离级别: REPEATABLE-READ

1. 创建测试表
DROP TABLE IF EXISTS `tb_task`;
CREATE TABLE `tb_task` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `task_id` int(11),
  `order_id` int(11),
  `tx` varchar(8),
  PRIMARY KEY (`id`),
  UNIQUE KEY `uk_taskid_orderid` (`task_id`,`order_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
2. 分别创建两个SQL会话,并开启事务

在这里插入图片描述

  1. 在事务1 中执行插入语句1INSERT tb_task(task_id,order_id,tx)values(1,123,'tx_1');
  2. 在事务2 中执行插入语句2INSERT tb_task(task_id,order_id,tx)values(1,213,'tx_2');
  3. 在事务1 中执行插入语句2INSERT tb_task(task_id,order_id,tx)values(1,213,'tx_1');
  4. 在事务2 中执行插入语句1INSERT tb_task(task_id,order_id,tx)values(1,123,'tx_2');
    在这里插入图片描述

在执行完上面的步骤后,可以看到事务2由于发生了死锁异常而导致事务被回滚,而事务1 的插入语句1的SQL执行成功.

在执行插入语句的过程中你可能已经注意到在执行第3步插入SQL时事务1并没有立即返回而是发生了阻塞,在事务2由于死锁导致报错回滚后事务1才执行了返回。

其实我们可以根据阻塞进行推测是由于在执行第3步插入操作时事务1尝试获取由事务2持有的锁,而事务2还没有结束导致的阻塞,而事务2在尝试插入事务1已经插入的SQL时系统检测到事务1和事务2可能会出现互相持有锁的情况而发生死锁从而抛出死锁异常并回滚事务2,此时由于事务2被回滚,其持有的锁被释放,因此事务1顺利获取到了锁从阻塞状态返回。

我们此时提交事务1并查看表中数据,可以看到表中存在两条由事务1提交的数据。
在这里插入图片描述
我们可以使用SQL命令SHOW ENGINE InnoDB STATUS\G查看最近一次死锁产生的原因:
在这里插入图片描述
更详细的原因分析看参考资料吧,这里就不重复赘述了。

参考资料

MySQL:insert 加锁与死锁分析
mysql insert锁机制(博客园)
mysql insert锁机制(优快云)

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值