SQL sync_binlog=1 vs 0 vs N 的耐久性与性能权衡在高写场景

2次阅读

会丢binlog;sync_binlog=0时依赖系统缓存,进程异常退出或断电会导致未刷盘binlog永久丢失,主从同步及pitr全部失效。

SQL sync_binlog=1 vs 0 vs N 的耐久性与性能权衡在高写场景

sync_binlog=0 时 mysql 会丢 binlog 吗?

会,而且很可能丢。当 sync_binlog=0 时,MySQL 完全依赖操作系统缓存刷盘,只要 mysqld 进程异常退出(比如 OOM kill、kill -9、服务器断电),还没来得及写入磁盘的 binlog 就永久丢失。主从同步、基于 binlog 的恢复、闪回等全部失效。

常见错误现象:SHOW SLAVE STATUS 报错 Could not find first log file name in binary log index file,或从库突然跳过大量事务;用 mysqlbinlog 解析最新 binlog 文件发现末尾不完整甚至为空。

  • 仅适合开发/测试环境,且能接受数据不可恢复
  • 不能用于任何需要主从一致性或 PITR(时间点恢复)的场景
  • 即使 innodb_flush_log_at_trx_commit=1,也不能弥补 binlog 丢失——两者是独立刷盘路径

sync_binlog=1 是最安全的选择吗?

是耐久性最强的设置,但不是“绝对安全”的银弹。它要求每次事务提交都调用 fsync() 刷 binlog 文件到磁盘,确保 binlog 和 InnoDB redo log 同时落盘(配合 innodb_flush_log_at_trx_commit=1),从而满足 ACID 中的 D(Durability)。

使用场景:金融、订单、支付等强一致要求系统;开启 GTID 且依赖 binlog 做逻辑复制的集群。

  • 性能代价明显:高并发写入下,IOPS 瓶颈常卡在 binlog 的 fsync()
  • SSD 能缓解但不消除延迟;NVMe 盘比 SATA SSD 好约 2–3 倍吞吐
  • 注意文件系统影响:XFS 比 ext4 在大文件 fsync() 场景更稳定,ext4 的 journal 模式可能引入额外延迟

sync_binlog=N(N>1)怎么平衡丢数据风险和性能?

这是生产中最常被低估的折中方案。设为 sync_binlog=100 表示每累积 100 个事务才刷一次盘,既降低 fsync() 频次,又把最大丢失窗口控制在最近 N 个事务内(不是时间)。

关键理解点:N 不是“每 N 秒”,而是“每 N 个 commit 事件”。如果 QPS 是 5000,sync_binlog=100 ≈ 每 20ms 刷一次;若 QPS 掉到 100,则变成每秒刷一次。

  • 必须配合监控:关注 Binlog_cache_useBinlog_cache_disk_use,后者非零说明事务太大,缓存溢出到磁盘临时文件,反而更慢
  • N 取值建议:从 10 或 50 开始压测,观察 Com_commit 延迟和 os.avg-disk-wait,避免盲目设成 1000+
  • 注意 replication lag 波动:从库 IO 线程读取的是已刷盘的 binlog,所以 N 越大,主库“看起来”越快,但从库延迟抖动可能变大

为什么有些线上库设了 sync_binlog=1 却还是丢 binlog?

常见原因不是配置没生效,而是被更高优先级机制绕过了。最典型的是 binlog_format=STATEMENT 下执行了非确定性函数(如 NOW()UUID()、用户变量),导致 MySQL 自动降级为 MIXED 并跳过某些事务的 binlog 记录;或者开启了 binlog_ignore_db 但匹配逻辑有误。

另一个隐蔽坑:sync_binlog 只对 *事务性* 写入生效。DDL(如 ALTER table)在 MySQL 5.7+ 默认自动提交且不走事务缓存,其 binlog 刷盘行为受 sync_binlog 控制,但某些中间件或 ORM 的“伪事务”(autocommit=1 下连续 execute)可能让 dba 误判刷盘节奏。

  • 务必确认 select @@sync_binlog 返回值,而不是只看配置文件——动态修改后需验证
  • 检查 SHOW VARIABLES LIKE 'binlog_format'binlog_row_image,ROW 格式下更容易追踪实际写入内容
  • strace -p $(pgrep mysqld) -e trace=fsync,write 抓真实系统调用,比日志更准

事情说清了就结束。真正难的不是选 0、1 还是 N,而是你得清楚自己能容忍几个事务不落地,以及磁盘到底能不能扛住那个 fsync 频率。

text=ZqhQzanResources