目录
- 概述
- 问题重现与解析
- Innodb lock机制
概述
正在奋力写"BUG"中,同事说出现死锁了,让帮忙看一下,so 放下手中工作,去瞅瞅, 一段很简单的代码,就是mysql数据库下使用多线程先删除数据再插入数据,造成了死锁
顺便骗个赞,觉得写的还可以的,不要吝啬你的赞哟
问题重现与解析
代码
代码解释:
第一张图,同事采用发令枪,多线程批量处理一批数据
第二张图是批量处理数据的逻辑, 在一个事务中,先删除一条数据然后再插入一批数据
异常提示
堆栈异常: Deadlock found when trying to get lock; try restarting transaction; 意思很明了,就是尝试获取锁时发现死锁.
疑惑
这段代码做删除时,使用的索引列,凭直观理解,这应该只是个行级锁, 不应该会出现死锁的,看代码很清楚的理解到,每个线程持有一个事务操作,如果是行级锁肯定不会出现死锁,所以删除的时候肯定不止锁了一条数据
拨云见日
在生产环境中mysql的存储引擎绝大部分是 InnoDB ,为什么使用 InnoDB 呢? 点击查看详细答案, 就凭事务安全这一条,相信足以让选择InnoDb了。
代码中delete操作的是非唯一索引列在innoDB引擎下会触发 next-key lock(间隙锁)。
举例: 表t中有非唯一索引列 test_id为 1, 10, 18, 22, 26的5条数据,此时模拟操作:
事务A 删除一条不存在的数据,数据库就会去找从左开始找最近的索引值
delete from t where test_id= 27;
事务B 删除一条不存在的数据,数据库就会去找从左开始找最近的索引值
delete from t where test_id= 28;
此时事务A和B就会分别产生一个(26,正无穷)间隙锁,然后继续操作
事务A
INSERT INTO t VALUES(27);
此时事务A阻塞,因为事务B在删除操作时拥有了区间锁
事务B</