mysql 8.0. 20 重新设计了doublewrite 机制,彻底解决了困扰社区多年的写入性能问题

MySQL 8.0.20这次更新带来了一个惊喜,写入性能竟然提升了10倍。这得益于MySQL 8.0.20重新设计了doublewrite机制,彻底解决了困扰社区多年的写入性能问题。这次测试使用了不同的线程数,从128线程、256线程、512线程一直到1024线程,性能曲线不再像以前一样下降,反而比上一版本还要高出很多。 InnoDB引擎首次把“安全”和“极速”这两个概念同时写进了代码。当我们把innodb_doublewrite_files设置为8时,可以直观地看到线程是如何拆分的。协调者和工作者被完全分离,让锁竞争像洪水一样分流到多个文件中,每个文件再独立维护自己的刷新段。 回顾一下MySQL的发展历程,早期Master线程负责处理脏页刷新、undo回收和日志写入等任务,在IOPS低时可能会出现问题。这个问题在SSD时代就变得更明显了。用户只是按一下SELECT键就可能触发LRU尾页刷新,把查询线程拖得很慢。 为了解决这个问题,MySQL 5.6引入了Page Cleaner后台线程来接管脏页刷新任务。Master线程终于可以卸下这个重担。LRU刷新也被移到了后台,SELECT操作不再被脏页刷新影响。Page Cleaner自适应刷新通过日志增速来减少延迟。 到了MySQL 5.7,InnoDB把大缓冲池切分成多个小块来减少latch冲突。虽然缓冲池被分割成多个实例,但每个脏页列表仍然对应一个刷新列表。这个设计没有完全发挥出并行潜力。 到了MySQL 8.0版本,官方对Redo模块进行了重构。他们先把log mutex这把“大锁”拆分成更细粒度的锁,让DML操作不再阻塞重做日志写入。 这次MySQL 8.0.20的更新又针对doublewrite机制进行了改进。之前doublewrite机制在高并发场景下容易出现锁竞争,导致写入速度变慢。官方把一个doublewrite对象拆分成4个独立文件,每个文件自带两个刷新段:一个是FLUSH_LIST负责顺序写入脏页,另一个是LRU_LIST负责随机写入LRU尾页。 这种设计让协调者和工作者分离开来,“分流洪水”一样把锁竞争分散到不同文件中。官方还提供了innodb_doublewrite_files参数来控制分段数量(默认为2,可设置为4或8)。 官方进行了压测测试:128、256、512、1024线程持续写入同一表时发现8.0.19版本存在抖动问题;升级到8.0.20后,吞吐量不再下滑,反而比上一版本高出10倍有余。 InnoDB的优化路径一直是在把串行变并行、热点变冷点、大锁变小锁。虽然这次更新让doublewrite不再拖后腿,但在极端并发场景下才能看到这个效果安全与性能终于达到了平衡,但仍然需要合理配置参数才能充分发挥性能潜力下一个版本还会给我们带来什么惊喜呢?我们拭目以待吧!