升级mysql大版本前必须锁定binlog_format为row并验证主从兼容性,滚动升级从库后精确对齐位点,迁移binlog需同步文件、index及权限,升级后立即禁用自动清理并校验连续性。

升级前必须锁定 binlog_format 并验证兼容性
MySQL 大版本升级(如 5.7 → 8.0)时,binlog_format 的默认值可能变更(例如 8.0 默认更倾向 ROW),而从库若仍用旧版 MySQL 解析新格式事件,容易报 Unknown binlog event type 或解析失败。这不是 bug,而是官方明确的复制不兼容场景。
- 执行
SHOW VARIABLES LIKE 'binlog_format';确认主从当前值一致,升级前统一设为ROW(推荐)或MIXED,避免依赖默认行为 - 在
my.cnf中显式写死:binlog-format = ROW,而非仅靠SET GLOBAL临时设置(重启即失效) - 查官方文档“Replication Compatibility”章节,确认目标版本是否支持你当前的 binlog 事件结构(例如 8.0.33+ 对
WriteRowsEvent v2支持更稳,旧从库可能不识别)
主从不能同时升级:必须滚动切换并校验位点
直接停主库、全量升级再拉起,会导致 binlog 断层——新主库生成的首个 binlog 文件(如 mysql-bin.000012)与原从库期望续接的文件(如 mysql-bin.000011)不连续,复制中断。
- 先升级一个从库:停服务 → 替换二进制 → 启动 → 执行
SHOW SLAVE STATUS\G,确认Seconds_Behind_Master = 0且Exec_Master_Log_Pos持续推进 - 记录原主库位点:
SHOW MASTER STATUS;输出的File和Position必须抄下来,这是后续人工对齐的唯一锚点 - 提升该从库为主后,原主库降级为从库时,需用
CHANGE MASTER TO ... MASTER_LOG_FILE='...', MASTER_LOG_POS=...精确指定起点,不能依赖MASTER_AUTO_POSITION=1(GTID 在跨大版本时易出错)
binlog 文件迁移 ≠ 直接拷贝:路径、权限、索引三者缺一不可
把旧实例的 /var/lib/mysql/mysql-bin.* 文件直接拷到新实例目录下,99% 会失败——MySQL 启动时会校验 mysql-bin.index 内容与实际文件名是否匹配,且要求文件属主为 mysql 用户、权限为 640。
- 若需复用历史 binlog(如审计、闪回),先在旧实例执行
FLUSH LOGS;确保当前日志已落盘,再用cp+chown mysql:mysql+chmod 640三步操作 - 新实例的
my.cnf中log-bin路径必须与拷贝目标路径一致;否则 MySQL 会忽略这些文件,自建新序列 - 启动后立刻执行
SHOW BINARY LOGS;,检查列表是否包含迁移来的文件名;若缺失,说明index文件未更新或路径配置错位
升级后立即禁用自动清理,手动验证 binlog 连续性
MySQL 8.0.23+ 默认启用 binlog_expire_logs_auto_purge = ON,若升级后未及时检查,旧 binlog 可能被自动删掉,导致无法回溯升级前的操作。
- 升级完成首小时内,执行
SET GLOBAL binlog_expire_logs_auto_purge = OFF;暂停自动清理 - 用
mysqlbinlog --base64-output=decode-rows -v /path/to/mysql-bin.000011 | tail -20查看末尾事件,再对比新主库的mysql-bin.000012开头是否有Rotate事件指向前者,这是 binlog 连续的关键证据 - 确认无误后,再按需开启清理:
SET GLOBAL binlog_expire_logs_seconds = 604800;(7天)
真正麻烦的从来不是命令怎么敲,而是位点没记、格式没锁、index 没同步这三处——它们不会报错,但会让复制在某天凌晨突然卡住,且错误日志里只有一行模糊的 Could not parse relay log event entry。










