背景
MySQL-8.0在InnoDB的性能方面做了很多改进,其中一个非常重要的改进是对Redo的改进。 MySQL-8.0对Redo的写和持久化(Flush)过程进行了重新的设计,因此MySQL-8.0上,写的性 能有很大的提升。但是这个性能的提升是在关闭Binlog的情形下的性能提升。当开启Binlog 后,性能的提升并不明显。详细的性能对比,感兴趣的同学可以访问Dimitri博客。他的文 章《MySQL Performance: 8.0 RW & Binlog impact 》对开启binlog和关闭binlog的性能做了对比。
Binlog是MySQL高可用、备份的基础。绝大多数的场景下,都需要开启Binlog。因此AliSQL 团队对Binlog的性能优化方面做了很多的探索和尝试,希望在开启Binlog时,也能够有很好 的性能提升。
Commit过程中的IO瓶颈
如上图所示,在事务的提交过程中有两次存储IO的写操作。第一次是Redo的写操作,将事务 的Prepare状态持久化。第二次是Binlog的写操作,将事务的Binlog Events持久化。这是一 个精心设计的过程,2次IO操作,保证了Binlog和引擎中数据的一致性。但是在事务的提交 过程中,存储IO的写操作是一个比较慢的过程,尤其对于网络存储更是如此。2次IO写操作 对事务的提交性能有很大的影响。
那么有没有办法在减少1次IO的情况下,又能保证Binlog和数据的一致性呢?答案是有的, 而且无论去掉Redo的Sync还是Binlog的Sync都可以保证Binlog和数据的一致性。
Binlog In Redo
最终我们选择去掉Binlog Sync。这个方案中需要将Binlog写入InnoDB Redo Log。因此称作 Binlog In Redo。之所以选择这个方案,除了性能更好之外,也是因为这个设计对Polar DB 也非常重要。
设计
当事务提交时,将事务的Binlog Events写入到Redo中,然后将Redo持久化。而Binlog文件 则采用异步的方式,用单独的线程周期性的持久化到存储中。因此事务的提交过程中,减少 了一次IO。
在主机宕机发生时,Binlog中可能会丢失Binlog Events. 重新启动时,Recovery过程会用 Redo Log中的Binlog Events来补齐Binlog文件。
这个设计从数据保护上保持了双1配置的含义,从性能上则去掉了Binlog的刷盘。由于减少 了一次IO操作,性能得到了提升,RT变的更小。Binlog文件刷盘次数的减少,极大地减少了 文件系统因文件长度实时变化带来的fsync压力,也提升了文件系统的性能。
性能
测试环境
RDS规格: 32Core, 64G Ram, ESSD存储。
测试工具: sysbench
oltp_update_non_index
oltp_insert
oltp_write_only
olpt_update_non_index和oltp_insert都属于单语句事务。oltp_write_only是多语句事务, 包含2个UPDATE,一个DELETE,一个INSERT。olpt_update_non_index和oltp_insert的事务提 交次数比oltp_write_only要多很多,所以olpt_update_non_index和oltp_insert的性能提 升比oltp_write_only更为明显。
Binlog Fsync 次数对比
开起binlog in redo功能时,Binlog fsync的次数要少非常多。
结论
Binlog In Redo功能在不损失可靠性的前提下,减少了1次存储IO. 在不超过256并发的情况 下,Binlog In Redo功能对性能的提升和延迟的降低都非常显著。对绝大多数的实际使用场 景来说,这个功能的效果非常明显。
Binlog In Redo 已经在RDS 8.0 20200430版本中发布,欢迎使用。