mysql 8.0. 20让写入性能一下子提升了十倍,背后靠的就是对doublewrite 机制的改动

MySQL 8.0.20版本让写入性能一下子提升了十倍,背后靠的就是对doublewrite机制的改动。这次更新给大家带来了不小的惊喜,把一直困扰社区的写入速度变慢问题彻底解决了。在这次测试中,不论压力有多大,性能曲线都没有出现下降的情况,反而比之前的版本还要好很多,最高甚至可以提高到10倍。这是因为InnoDB存储引擎第一次把安全和速度同时做到了极致。从上面的图片可以看到,当innodb_doublewrite_files参数设置为8时,系统就把协调者和工作者分开了。这样一来,每个文件都能独立处理自己的刷新工作,锁竞争就像是洪水被分流一样。 回想一下MySQL的发展历史。早期MySQL 5.5版本里,Master线程需要同时处理脏页刷新、undo回收和日志写入等任务。当IOPS比较低的时候问题不明显,但是在SSD时代就容易出问题。而且用户随便执行一个SELECT查询也可能会触发LRU尾页刷新,让查询变得很慢。后来MySQL 5.6版本里引入了Page Cleaner后台线程来负责脏页刷新,Master线程就不用那么累了。同时还加上了自适应刷新功能来减少延迟,LRU刷新也移到了后台进行。 到了MySQL 5.7版本的时候又做了一些改进:把大缓冲池切成多块减少了冲突。不过每个脏页列表还是对应一个刷新列表,Page Cleaner还是只有一条线运行。虽然这个版本增加了手动添加线程的选项,但是默认还是绑定在单一缓冲池实例上。 再看现在MySQL 8.0版本:重新设计了Redo模块,先把大锁拆细再拆分文件。这次把 log mutex这把大锁拆成更细粒度的锁,DML操作不会再轻易被阻塞。而且官方也把目光转向了doublewrite缓冲区。 以前doublewrite设计是为了防止硬件损坏导致数据丢失:先把脏页复制到内存中再随机写入磁盘。问题在于这个过程需要串行拿锁导致竞争激烈:在高并发情况下速度会大幅下降。 8.0.20版本默认把doublewrite对象切成4个独立文件:每个文件有两个刷新段:一个负责脏页顺序写入(FLUSH_LIST),另一个负责LRU尾页随机写入(LRU_LIST)。用户可以通过调整 innodb_doublewrite_files 参数控制分段数量。协调者和工作者分离后锁竞争就被分流到不同文件里去了。 官方压测显示:不管用128、256、512还是1024线程持续写入同一张表,8.0.19版本会出现明显抖动;但升级到8.0.20之后吞吐量不仅没下降反而高出了10倍以上。 从缓冲池切片到Page Cleaner多线程再到这次doublewrite拆分:InnoDB一直坚持把串行变成并行、把热点变成冷门、把大锁变成小锁这个优化路径。虽然8.0.20让doublewrite不再拖后腿了,但要想获得最高性能还是需要合理配置参数才行。接下来还会有什么惊喜等着我们呢?让我们拭目以待吧。