双1配置锁住redo log和binlog两道落盘门,因innodb_flush_log_at_trx_commit=1和sync_binlog=1分别强制二者刷盘,缺一不可,共同保障rpo=0。

双1配置到底锁住了哪两道落盘门
因为 innodb_flush_log_at_trx_commit=1 和 sync_binlog=1 分别控制 redo log 和 binlog 的强制刷盘行为,缺一不可。redo log 保证崩溃后已提交事务可恢复,binlog 保证主从复制不丢事务——两者共同构成 RPO=0 的底线。只开一个,另一条链路就成单点故障。
异步刷盘在高可用链路上埋了什么雷
常见错误现象是:主库没报错、从库延迟突增、切换后发现最后几秒订单丢失。这往往不是复制本身慢,而是主库把 binlog 或 redo log 滞留在 OS cache 里没真正落盘,一旦主库断电或内核 panic,这部分日志就永远消失。半同步复制(semi-sync)下更危险:主库等到了从库 ACK,但自己还没把 binlog fsync 到磁盘,此时主库宕机,从库有日志、主库日志却丢了,数据不一致。
-
sync_binlog=0:每次提交只 write 到 page cache,依赖 OS 每秒 flush,断电即丢最近一批 binlog -
innodb_flush_log_at_trx_commit=2:redo log 只写入 page cache,MySQL 崩溃不丢,但断电可能丢 1 秒内已提交事务 - 两者叠加时,即使开启半同步,RPO 实际退化为“最多丢 1 秒”,和高可用目标直接冲突
为什么实测中双1反而提升 QPS
这不是玄学,是 group commit 在起作用。当并发高、事务小、提交频繁时,多个事务的 redo log 和 binlog 可被合并为一次 fsync。操作系统和磁盘层对顺序批量刷盘的优化远超预期,反而比零散 write + 随机刷盘更高效。尤其在 NVMe SSD 或带掉电保护(PLP)的企业级磁盘上,fsync 延迟稳定在 100–300μs 级别,而 OS cache 路径因锁竞争(如 log_sys mutex)导致的排队延迟动辄几毫秒。
- 双1 启用 group commit 后,每毫秒可打包 20+ 事务一起刷盘
- 异步模式下看似“快”,实则每个事务都在争抢 log buffer 写入锁,提交路径串行化严重
- 压测中 QPS 上涨 38% 的本质,是锁竞争下降 + IO 合并增效,不是 fsync 本身变快
双1生效的前提条件容易被忽略
双1 不是设了参数就自动生效的魔法开关。它依赖底层硬件和系统配置协同工作:
- 文件系统必须禁用 write barrier 绕过(如 XFS 的
barrier=0会破坏双1 语义) - 存储设备不能启用 write cache 且无掉电保护(例如普通 SATA SSD 开启缓存但没电容,
fsync会假成功) - MySQL 必须运行在支持 O_DIRECT 或 O_SYNC 的挂载选项下(ext4 的
data=ordered不足,推荐data=journal或 XFS) -
innodb_doublewrite=ON必须保持开启,否则页面断裂(torn page)风险会让 redo log 恢复失败
最常被跳过的一步是验证磁盘是否真实响应 fsync:用 dd if=/dev/zero of=test bs=4k count=1000 oflag=direct && sync 测延迟,再对比 strace -e trace=fsync mysql -e "commit" 看实际耗时——很多所谓“双1”环境,fsync 调用根本没走到磁盘驱动层。











