一、死锁案例
MySQL版本:Percona MySQL Server 5.7.19
隔离级别:可重复读(RR)
业务逻辑:并发下按某个索引字段先delete记录,再insert记录
比如:begin;delete from tb where order_id = xxx;insert into tb(order_id) values(xxx);
commit;
二、MySQL锁基本概念
S:共享锁(行级锁)
X:排他锁(行级锁)
IS:意向共享锁(表级锁)
IX:意向排他锁(表级锁)
以上4种锁的兼容性见下表:
锁模式兼容性表gap锁与gap锁之间不冲突
rec insert intention(插入意向锁)与gap锁冲突。
三、模拟复现死锁
打开参数,从innodb status获取更多的锁信息。
set GLOBAL innodb_status_output_locks=ON;
表结构:CREATE TABLE `tb` ( `order_id` int(11) DEFAULT NULL,
KEY `idx_order_id` (`order_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8
表中数据:mysql> select * from tb;
+----------+| order_id |+----------+| 10 || 20 |+----------+2 rows in set (0.00 sec)
事务执行步骤:session1session2begin
begin
delete from tb where order_id=15;
delete from tb where order_id=15;
insert into tb select 15;(等待锁)
insert into tb select 15;(死锁)当session1执行delete from tb where order_id=15;,由于条件order_id=15的记录不存在,session1 获得2个