最近更新时间:2025-10-31 21:52:50
在事务的提交过程中有两次存储IO的写操作,第一次是Redo的写操作,将事务 的Prepare状态持久化。第二次是Binlog的写操作,将事务的Binlog Events持久化。2次IO操作,保证了Binlog和引擎中数据的一致性。但是在事务的提交过程中,存储IO的写操作是一个比较慢的过程,尤其对于云盘更是如此,2次IO写操作对事务的提交性能有很大的影响。
在双1前提下,每个事务提交会对磁盘进行两次I/O操作,虽然Binlog采用了Group Commit的方式合并I/O来提升效率,但两次I/O等待的本质没有改变,影响事务处理的效率,当使用云盘存储时,影响会更明显。
另一方面,组提交I/O合并的效率是由同时提交的并发事务数量决定的,当并发量不够时,I/O合并的效果也不理想,表现为少量的写操作事务提交时所需要的时间比较久,响应时间较长。
为了提高事务提交效率,KingSQL开发了Binlog in Redo特性,概括来说把 Binlog 转成一种 Redo Type,在事务提交时有序的将Binlog内容同步写入到Redo Log中:
在这个架构下,binlog 对于 redo log 来说也是一份“数据”,受到 redo log 的保护;binlog 的刷盘由异步线程完成,事务提交过程中,无需等待 binlog 刷盘。如果发生 crash,根据 redo log 恢复binlog 文件即可。
binlog写入redo
ordered commit阶段写入binlog到redo log
异步sync线程
异步sync binlog文件,之后更新binlog commit lsn,推进checkpoint
崩溃恢复
Crash Recovery阶段从redo中解析binlog,并恢复最近的binlog文件
Crash Recovery过程中,无论是否开启binlog in redo功能,都应该尝试恢复binlog日志,因为进程启动时,并不知道先前crash时候,是否开启了binlog in redo。故只要遇到MLOG_BINLOG_IN_REDO_INFO类型的redo log,就要进行恢复操作。
抽象一个Binlog_applier对象,实现Crash Rrecovery恢复逻辑。Binlog_applier包括3个动作:
1)open_applier:定位并打开最新的binlog文件;
2)apply_binlog:解析redo中的binlog event,追加到binlog文件中;
3)close_applier:关闭binlog文件;
mysql> show global variables like '%binlog_in_redo%';
+------------------------------+----------+
| Variable_name | Value |
+------------------------------+----------+
| enable_binlog_in_redo | ON | //控制binlog in redo 开关
| binlog_in_redo_sync_interval | 50 | //异步线程循环执行周期
| binlog_in_redo_cache_size |20971520 | //binlog in redo cache大小
+------------------------------+----------+
3 rows in set (0.07 sec)mysql> show global status like '%binlog_in_redo%';
+-----------------------------------------------------+----------+
| Variable_name | Value |
+-----------------------------------------------------+----------+
| Binlog_in_redo_async_count | 1 |
| Binlog_in_redo_async_error_count | 0 |
| Binlog_in_redo_batch_count | 0 |
| Binlog_in_redo_flushed_lsn | 0 |
| Binlog_in_redo_last_sleep_us | 50000 |
| Binlog_in_redo_skip_batch_count | 0 |
| Binlog_in_redo_sync_thread_alive | RUNNING |
| Innodb_binlog_in_redo_synced_lsn | 19494243 |
| Innodb_binlog_in_redo_diff_from_last_checkpoint_lsn | 0 |
| Innodb_binlog_in_redo_diff_from_flushed_to_disk_lsn | 0 |
| Innodb_binlog_in_redo_diff_from_write_lsn | 0 |
+-----------------------------------------------------+----------+
11 rows in set (0.00 sec)测试工具: sysbench
机器规格:32C128G |
buffer pool 32G |
tables = 64 table_size=1000000 |
读写场景,中低并发性能提高1~35%(8-256),高并发性能基本持平(512并发以上)
只写场景,中低并发性能提高3~28%(8-256),高并发性能基本持平(512并发以上)
insert场景,性能提高3~47%(8-256),高并发提高1~3%(512以上)。
机器规格:8C16G 500G PL1硬盘 |
buffer pool 4G |
tables = 64 table_size=1000000 |
云原生数据库模式下计算节点和存储节点之间的带宽资源变得更加珍贵,而binlog in redo极大节省了事务提交过程中IO使用。binlog in redo 功能对性能的提升和延迟的降低都非常显著,但是对于大并发的场景,性能提升效果有限。
这是由于大并发下,组提交合并 IO 的作用更加明显,Binlog 提交期间的瓶颈来到了串行化的 write binlog,另外高并发场景下GTID分配与释放的锁竞争问题。
未来工作主要思路是将flush阶段消耗CPU的部分并行,减少flush阶段耗时。(GTID event对象的生成,binlog cache的解析和填补,都是繁重的CPU工作)。
纯净模式
