MySQL 8.0 启动时硬编码设为ROW,但必须在my.cnf的[mysqld]段显式配置binlog_format=ROW并重启才真正生效;主从配置必须严格一致,否则复制中断或CDC工具解析失败。

MySQL 8.0 启动时 binlog_format 默认就是 ROW,但不等于已生效
你查 SELECT @@global.binlog_format 返回 ROW,不代表配置真正起作用。MySQL 8.0 启动时若 my.cnf 的 [mysqld] 段没写 binlog_format = ROW,它会硬编码设为 ROW —— 但这只是运行时值,不是持久化配置。升级 5.7 → 8.0 后复制中断、CDC 工具报错,八成是主从 my.cnf 里压根没这行,或写在了 [client] 段下。
-
binlog_format必须放在[mysqld]段,等号前后不能有空格 -
SET GLOBAL binlog_format = 'ROW'对已有连接无效,更不影响 SQL 线程 - 云厂商镜像可能默认开启
binlog_transaction_compression = ON,导致本地mysqlbinlog解析失败,需加--binlog-row-event-max-size或关压缩
STATEMENT 格式在 MySQL 8.0 下会被主动拦截,不是兼容性问题
执行含 NOW()、UUID()、@variable 或未声明 DETERMINISTIC 的自定义函数的语句时,MySQL 8.0 直接拒绝写入 binlog,报错 Statement is not safe to log in statement format。这不是 bug,是安全策略:宁可事务失败,也不让非确定性日志进入复制链路。
- 哪怕只有一行
SET @ts = NOW();,整个存储过程在STATEMENT下就无法执行 - 启用 GTID 后,某些
STATEMENT语句会被强制降级为ROW,且不提示;从库若仍设为STATEMENT,直接报The slave is running with binlog_format = STATEMENT, but the master sent a ROW event -
MIXED不帮你兜底:它靠内置规则表硬匹配,对业务逻辑无感知,误判率高,且不提示切换动作
ROW 格式支撑现代数据链路,不是“可选”而是“必需”
Canal、Flink CDC、Maxwell、ShardingSphere 这些工具全依赖 ROW 日志里的行级变更快照。它们需要 before_image 和 after_image 做增量同步、审计回滚、精准闪回——STATEMENT 日志里只有 SQL 文本,没有这些信息。
-
mysqlbinlog --base64-output=DECODE-ROWS -v能直接看到被删的每一行原始数据,配合binlog_row_image = FULL(默认值),即使UPDATE只改一个字段,也能还原整行旧值 - 并行复制(
slave_parallel_type = LOGICAL_CLOCK)必须基于ROW事件才能正确分发事务 - 无主键表在
ROW模式下复制会严重延迟:MySQL 需全表扫描匹配条件行,无法走索引定位
主从 binlog_format 必须严格一致,否则复制启动就失败
从库 binlog_format 可设为 OFF(不开启 binlog),但若开启,必须与主库完全一致。否则启动复制时报错:The slave is running with binlog_format = STATEMENT, but the master sent a ROW event。这不是警告,是硬性校验。
- 检查真实生效值只能用
SELECT @@global.binlog_format,别信配置文件里写了就算数 - 旧从库(如 MySQL 5.7)无法识别 8.0.33+ 的
Write_rows_event_v2,必须核对官方 “Replication Compatibility” 表 -
ROW不记录存储过程调用本身,只记录其引发的 DML 事件(Write_rows_v1/Update_rows_v1),所以SHOW BINLOG EVENTS看不到CALL proc_name(),只看到后续的行变更
binlog_format = ROW 这一行,必须出现在主从的 [mysqld] 段里,重启生效,且两边值完全一致——少一个空格、多一个注释、配错段落,都会让复制链路在启动那一刻就断掉。


















