作者:微信小助手
发布时间:2022-07-12T01:10:49
作者:小林coding 八股文网站:xiaolincoding.com 大家好,我是小林。 之前分享过 MySQL 死锁的文章,然后很多读者对「插入意向锁」认识很迷糊。 大家误以为「插入意向锁」是意向锁,也就是表锁,确实这个名字很让人误解。 但是,实际上「插入意向锁」不是意向锁,而是特殊的间隙锁,属于行级锁,注意是「特殊」的间隙锁,并不是我们常说的间隙锁。 所以,我在原来文章的基础上补充了两个知识点: 提纲如下: 有个业务主要逻辑就是新增订单、修改订单、查询订单等操作。然后因为订单是不能重复的,所以当时在新增订单的时候做了幂等性校验,做法就是在新增订单记录之前,先通过 而正是因为这样的操作,当业务量很大的时候,就可能会出现死锁。 接下来跟大家聊下为什么会发生死锁,以及怎么避免死锁。 本次案例使用存储引擎 Innodb,隔离级别为可重复读(RR)。 接下来,我用实战的方式来带大家看看死锁是怎么发生的。 我建了一张订单表,其中 id 字段为主键索引,order_no 字段普通索引,也就是非唯一索引: 然后,先 假设这时有两事务,一个事务要插入订单 1007 ,另外一个事务要插入订单 1008,因为需要对订单做幂等性校验,所以两个事务先要查询该订单是否存在,不存在才插入记录,过程如下: 可以看到,两个事务都陷入了等待状态(前提没有打开死锁检测),也就是发生了死锁,因为都在相互等待对方释放锁。 这里在查询记录是否存在的时候,使用了 如果没有使用
正文
select ... for update
语句查询订单是否存在,如果不存在才插入订单记录。死锁的发生
CREATE TABLE `t_order` (
`id` int NOT NULL AUTO_INCREMENT,
`order_no` int DEFAULT NULL,
`create_date` datetime DEFAULT NULL,
PRIMARY KEY (`id`),
KEY `index_order` (`order_no`) USING BTREE
) ENGINE=InnoDB ;t_order
表里现在已经有了 6 条记录:
select ... for update
语句,目的为了防止事务执行的过程中,有其他事务插入了记录,而出现幻读的问题。