大事务提交,为什么总是"慢半拍"?
用过 MySQL / GreatSQL 的 DBA 大概都遇到过这样的场景:一个大事务提交,整个库仿佛被按了暂停键------TPS 突然抖动,其他事务排队等待,I/O 打满。
根子出在传统 binlog 的提交流程上。大事务提交时,要把已经落在磁盘上的 binlog cache 重新读出来,再二次写入 binlog 文件。这套"缓存回读 + 二次写入"的动作,带来一连串代价:
- 高 I/O 消耗,同样的数据要写两遍(写放大);
- 长时间持有 binlog 锁,阻塞其他事务提交;
- TPS 波动明显,高并发下尤为难受。
事务越大,这段路走得越痛。
GreatSQL 8.4.4-5 的解法:让binlog cache 文件"直接变身"binlog 文件
GreatSQL 在 8.4.4-5 版本带来了「大事务 binlog 独立落盘」特性。核心思路一句话:
不再回读重写,而是把 binlog cache 文件直接"转正"成 binlog 文件。
传统路径是:binlog cache → 读取 → 写入 binlog 文件 → 提交(存在二次 I/O)。
优化后路径变成:binlog cache → 预构建 → rename → 提交(零二次写 I/O)。
提交链路直接缩短,I/O 延迟自然大幅下降。
背后的三项关键改造
- 可重构的 cache 文件结构:binlog cache 在写入时就预留好 File Header、Format Description Event、Previous GTID、GTID Event 以及对齐 padding 空间,让它天生具备"可直接当 binlog 文件用"的结构。
- 直接 rename 落盘机制:满足条件时,结束当前 binlog 文件、把 header events 写入 cache 预留空间,再把 cache 文件直接 rename 成正式 binlog 文件。
- checksum 状态继承:独立落盘期间关闭 binlog checksum,后续写入同一文件的事务继承该状态,rotate 时同步传播,保证文件一致性。
性能收益:延迟降 30%~70%,TPS 提升 10%~40%
在大事务场景下,这套优化带来的收益相当直接:
- 大事务提交延迟降低 30%~70%;
- 高并发场景 TPS 提升 10%~40%;
- binlog 写放大减少,I/O wait 明显下降,TPS 波动收敛。
怎么用?一个参数就够
优化由参数 binlog_large_commit_threshold 控制:
- 类型:
ulonglong,默认值 128MB; - 含义:触发大事务优化的阈值,事务大小达到该值即启用。
启用还需满足几个条件:binlog cache 已发生落盘(非纯内存)、未混用 stmt/trx cache、未开启 binlog 压缩或加密、end_log_pos 校验通过。
稳不稳?兼容和回退都考虑到了
- 完全兼容 MySQL binlog 协议与 GTID 体系,
mysqlbinlog正常解析,不影响主从复制逻辑,不改变事务语义; - 遇到预留空间不足、end_log_pos 不一致、checksum 异常、文件系统失败等情况,会自动回退到传统写入模式,安全兜底;
- 开启 binlog 压缩 / 加密、cache 混用等场景不启用该优化,行为与原来一致。
一句话总结:GreatSQL 8.4.4-5 通过重构 binlog cache 文件模型,让大事务具备"零拷贝式落盘"能力,从根子上砍掉了 binlog 写入路径的 I/O 放大,是高负载场景下提升稳定性的一把利器。
特性详情见 GreatSQL 8.4.4-5 官方文档:
https://greatsql.cn/docs/8.4.4-5/5-enhance/5-1-highperf-binlog-flush-opt-large-trx.html