直接回答:redo log 是 InnoDB 引擎层的物理日志,保证已提交事务崩溃不丢;binlog 是 Server 层的逻辑日志,用于主从复制和时间点恢复。两份日志必须“同时成功或同时失败”,否则主库数据与从库、备份恢复结果不一致——比如 redo 已提交而 binlog 没写完,崩溃后主库有这条数据、从库永远没有。解法是内部 XA 两阶段提交:prepare 阶段写 redo 并标记 prepare,然后写 binlog,最后 redo 记 commit,三个步骤任一失败都能推导出一致结果。
展开解析:崩溃恢复规则:启动时扫描 redo,对处于 prepare 状态的事务,拿事务 XID 去 binlog 中查找——binlog 中有完整记录则提交该事务(补 redo commit),binlog 中缺失则回滚(走 undo log)。这样保证 redo 与 binlog 逻辑等价,主从不会分叉。性能上靠组提交(group commit)把多个事务的 prepare、写 binlog、fsync 合并成一轮流水线,一次 fsync 落盘一批事务;binlog_group_commit_sync_delay 可牺牲几十微秒延迟攒更多事务提高吞吐。可靠性由两个参数控制:innodb_flush_log_at_trx_commit=1 且 sync_binlog=1 才是完整的“双 1”配置,牺牲性能换不丢数据。5.7 起从库并行复制的 LOGICAL_CLOCK 也依赖 binlog 组提交标记同一批事务可并行回放。
实践要点:主从一致性排查时,“双 1”和 relay_log_recovery 是首要检查项。
追问方向:为什么 prepare 之后崩溃的事务还能安全提交?组提交如何减少 fsync 次数?sync_binlog=0 的丢数据窗口有多大? (约 365 字)