现在很多业务还是用的mysql5.6,一直看到有很多人分享mysql 8.0性能提升了多少,新功能有多好用,最近看到叶金荣老师分享的mysql 8.0.19 解决了一个20多年的“BUG”,就安装试了一下。
mysql 8 版本存在的一个坑
急匆匆的在本地用最新的phpstudy(懒,直接用的集成环境)安装了MYSQL8,创建表结构:
Create Table: CREATE TABLE `t1` (
`c1` int(10) unsigned NOT NULL DEFAULT '0',
`c2` int(10) unsigned NOT NULL DEFAULT '0',
`c3` int(10) unsigned NOT NULL DEFAULT '0',
`c4` int(10) unsigned NOT NULL DEFAULT '0',
PRIMARY KEY (`c1`),
KEY `c2` (`c2`)
) ENGINE=InnoDB;
插入数据如下:
±—±---±—±---+
| c1 | c2 | c3 | c4 |
±—±---±—±---+
| 0 | 0 | 0 | 0 |
| 1 | 1 | 1 | 0 |
| 3 | 3 | 3 | 0 |
| 4 | 2 | 2 | 0 |
±—±---±—±---+
开启2个会话:
A | B |
---|---|
SET AUTOCOMMIT=0; | SET AUTOCOMMIT=0; |
START TRANSACTION; | START TRANSACTION; |
select * from t1 where c1<=1 for update; | |
delete from t1 where c1=3; |
先说一下MYSQL 5.7以及之前的版本的一个问题,next-key lock的锁范围会被扩大,也就是deletel这句话会被阻塞,因为我想锁定的是主键c1<=1也就是0 和1这2条记录,但是实际c1=3这条记录也是被锁住的,之前丁奇老师也提过这个问题,认为是mysql的一个bug。
引用叶老师的描述:
InnoDB行锁规则上,有这样的一个原则:
对有唯一属性的索引(主键/唯一索引)进行范围条件加锁时,
向右遍历(假设是普通正序索引,而且不加ORDER BY … DESC约束)过程中,
会一直扫描并加next-key锁到第一个不满足条件的记录为止,
但如果是RC级别,这个next-key lock会退化成gap lock,而RR下不会退化。
简言之,就是 “锁会被扩大化”,从InnoDB引擎诞生以来一直都是如此。
其实严格来说,这个算是问题或缺陷,甚至也可以认为是bug。
mysql8.0解决了这个问题,但是我测试的时候执行 delete 还是被阻塞了112.53秒,而且超时后竟然执行成功了。
这个什么情况!坑我呢~~
又去看了一下叶老师的文章,原来叶老师提到的mysql版本是 8.0.18以上,看了一下我用phpstudy安装的版本是 8.0.12,于是又更新到8.0.16,和之前的5.6、5.7版本一样,会被阻塞而且回滚。
最后安装了8.0.19,测试的时候确实不会被阻塞了,而且删除成功了。
总结
1 MYSQL 8.0.18以上确实解决了之前版本存在了20年的“BUG”。
2 引入新版本的时候要谨慎谨慎再谨慎,不然被坑是肯定的。
引用
叶金荣微信公众号:搜索 老叶茶馆