mysql 5.7 升级到 8.0 后 binlog_format 默认变为 mixed,因 8.0 不继承旧隐式默认值且忽略未显式配置的参数,必须在 my.cnf 的 [mysqld] 段中明确设置 binlog_format 并重启生效,主从需严格一致、滚动升级先改从库,并注意 binlog_transaction_compression 和 binlog_row_image 等配套参数匹配。

binlog_format 在 MySQL 5.7 升级到 8.0 后默认从 STATEMENT 变为 MIXED(部分云厂商镜像甚至直接设为 ROW),但你的主从复制、CDC 工具或审计系统可能强依赖 STATEMENT 格式,此时不能直接接受“升级后自动变”,必须主动干预。
为什么升级后 binlog_format 突然不一致了?
MySQL 8.0 不再继承旧版本的隐式默认值;它会忽略 my.cnf 中未显式声明的 binlog_format,哪怕你 5.7 时没配过,8.0 启动时也会按内置规则选一个(通常是 MIXED)。这不是 bug,是行为变更。
- 别只查
SELECT @@global.binlog_format—— 它返回的是当前运行值,不是配置文件真实生效值 - 必须检查
my.cnf的[mysqld]段里有没有binlog-format = STATEMENT(注意等号前后不能有空格,且键名写法要统一:官方推荐binlog_format,但binlog-format也兼容) - Percona Server 或 MariaDB 的默认策略不同,别照搬 Oracle MySQL 文档
主从都得改,而且顺序不能错
主库改成 ROW,从库还留着 STATEMENT?MySQL 8.0 启动时就会拒绝启动复制线程,报错:The slave is running with binlog_format = STATEMENT, but the master sent a ROW event。
- 滚动升级必须先改从库:停
STOP SLAVE→ 改配置 → 重启 mysqld →START SLAVE - 确认从库
Seconds_Behind_Master = 0且SHOW SLAVE STATUS\G中Slave_SQL_Running_State是Slave has read all relay log,再动主库 - 主库改完重启后,立刻执行
FLUSH LOGS,生成新 binlog 文件,避免混用格式日志 - 多源复制场景下,每个
CHANNEL都要单独验证,SHOW SLAVE STATUS FOR CHANNEL 'xxx'
mysqlbinlog 解析失败,大概率是压缩或版本不匹配
你用 mysqlbinlog /var/lib/mysql/mysql-bin.000012 报 unknown compression algorithm 或输出乱码?不是格式设错了,而是启用了 binlog_transaction_compression = ON(MySQL 8.0.20+ 默认关闭,但某些云厂商 OS 镜像默认开了)。
- 先查开关:
SELECT @@global.binlog_transaction_compression;,若为ON,解析必须加参数:mysqlbinlog --binlog-row-event-max-size=8192 --base64-output=DECODE-ROWS --verbose - 更稳妥的做法是关掉:
SET GLOBAL binlog_transaction_compression = OFF,并写入配置文件永久禁用 - 旧从库(如 5.7)无法解析 8.0.33+ 新增的
Write_rows_event_v2,必须核对官方文档的 “Replication Compatibility” 表,确认目标从库版本是否支持主库发出的事件类型
ROW 模式下日志暴涨,但别急着切回 STATEMENT
ROW 日志体积大是事实,尤其对含 TEXT/BLOB 字段的表做全量 UPDATE,单条日志可达 MB 级。但切回去会暴露非确定性函数(NOW()、UUID()、触发器逻辑)导致主从不一致。
- 优先调
binlog_row_image = MINIMAL(只记变更列),但它要求所有表有主键或唯一非空索引,否则自动降级为FULL - 业务层拆分大字段写入:避免
UPDATE t SET blob_col = ?,改用INSERT INTO t_log (tid, chunk) VALUES (?, ?)分片存 - 别信“
SET GLOBAL binlog_format = STATEMENT临时切回去” —— 这个设置只影响新连接,复制 SQL 线程根本不认,且重启即丢
mysqlbinlog 是否带对参数、以及 binlog_row_image 和表结构是否匹配。这些细节一漏,日志就断、复制就挂、解析就乱。











