错误:Deadlock found when trying to get lock; try restarting transaction
1.场景:
建表语句:
CREATE TABLE `aaa` (
`id` bigint(20) NOT NULL COMMENT '主键',
`schs_id` bigint(20) NOT NULL COMMENT '',
`sch_id` bigint(20) NOT NULL COMMENT '',
`rsp_status` bit(1) NOT NULL DEFAULT b'1' COMMENT '1 成功 0 失败',
PRIMARY KEY (`id`),
KEY `sch_id_status` (`sch_id`,`rsp_status`) USING BTREE
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='';
并发执行insert、update操作。
- update aaa SET rsp_status=0 where id in( SELECT a.id FROM ( select id from aaa as A where A.sch_id=462894582813392896 order by A.id limit 0 ,34 ) a )
- insert into aaa value();
2.Mysql锁类型分析
MySQL有三种锁的级别:页级、表级、行级,这个地方遇到的问题是来自于行级锁,所以重点说一下。
类型 | 特性 |
---|---|
表级锁 (table-level locking) | 开销小,加锁快;不会出现死锁;锁定粒度大,发生锁冲突的概率最高,并发度最低。 |
行级锁 (row-level locking) | 开销大,加锁慢;会出现死锁;锁定粒度最小,发生锁冲突的概率最低,并发度也最高。 |
页面锁 (page-level locking) | 开销和加锁时间界于表锁和行锁之间;会出现死锁;锁定粒度界于表锁和行锁之间,并发度一般。 |
行级锁在使用的时候并不是直接锁掉这行记录,而是锁索引
如果一条sql用到了主键索引(mysql主键自带索引),mysql会锁住主键索引;
如果一条sql操作了非主键索引,mysql会先锁住非主键索引,再锁定主键索引.
原因:
update 语句中使用到了sch_id非主键索引,则根据上述介绍,update操作会锁住sch_id索引和id索引(有点猜测成分)。这样进行insert的时候,sch_id索引被锁住,无法插入数据更新索引,导致死锁。
解决方案:
删除’sch_id_status’索引,执行表级锁。
https://blog.csdn.net/qq_44240587/article/details/108400666