为什么会死锁
数据准备
建个表
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 ;
存个数据
然后我们分别创建两个事务
事务A:插入订单 1007
事务B:插入订单 1008
由于插入之前要检测(for update)是否已经存在该条记录 所以执行流程是这样的
我们要知道 锁只是针对其他事务的 且锁只在本事务结束后才能释放
首先事务Aselect: 会锁住(1006,正无穷)
事务B select:会锁住(1006,正无穷)
(间隙锁可以共存 但是Next-key锁因为包含记录锁所以不能共存)
事务A insert 1007的下一条记录 找到了表示最大的虚拟记录 在间隙上放插入意向锁 然后发现这个间隙上面有事务B的间隙锁 阻塞(插入意向锁等待状态)
事务B insert 1008的下一条记录 找到了表示最大的虚拟记录 找到了表示最大的虚拟记录 在间隙上放插入意向锁 然后发现上面有事务B的间隙锁 阻塞
然后A和B因为insert操作阻塞 所以事务一直存在 所以锁一直存在 所以死锁
死锁的四个条件
互斥、占有且等待、不可强占用、循环等待
如何排查死锁
提示出现死锁:ERROR 1213 (40001): Deadlock found when trying to get lock; try restarting transaction
我们就知道死锁发生了
通过SHOW ENGINE INNODB STATUS;
来查看死锁日志:
根据死锁日志分析循环等待的场景,然后根据当前各个事务执行的SQL分析出加锁类型以及顺序,逆向推断出如何形成循环等待,这样就能找到死锁产生的原因了。