mysql 5.7 与 8.0 不能直接混搭主从复制,因 gtid 兼容性、binlog 格式、sql 模式等差异易导致复制中断或报错,官方仅支持同版本间复制。

MySQL 主从复制中 5.7 和 8.0 版本能否混搭?
不能直接混搭做主从,尤其是 5.7 作为主库、8.0 作为从库时,大概率会报错 ER_SLAVE_INCIDENT 或复制中断在 GTID_PURGED 初始化阶段。根本原因是 8.0 默认启用 enforce_gtid_consistency=ON 且要求所有事务带 GTID,而 5.7 的部分语句(如非事务性 DML、CREATE TEMPORARY TABLE)在未显式开启 gtid_mode=ON 时无法生成合法 GTID,导致从库拒绝执行。
实操建议:
- 若必须跨版本复制,仅允许
5.7(主)→5.7(从)或8.0(主)→8.0(从),这是官方唯一完全支持的组合 - 若已有
5.7主库想升级从库到8.0,先将主库升级至5.7.29+,再按 MySQL 官方“滚动升级”路径操作:主库保持gtid_mode=OFF,从库用binlog_format=ROW+skip_slave_start=1手动初始化,且禁止在从库执行任何写操作 -
SHOW SLAVE STATUS\G中若出现Retrieved_Gtid_Set为空但Executed_Gtid_Set有值,说明 GTID 同步已错乱,需重做从库
MySQL 8.0 主库搭配 5.7 从库为何启动就报 ERROR 1236?
典型错误是:Got fatal error 1236 from master when reading data from binary log: 'The slave is connecting using CHANGE MASTER TO MASTER_AUTO_POSITION = 1, but the master has purged binary logs containing GTIDs that the slave requires.' 这不是网络或权限问题,而是 8.0 主库默认开启 gtid_mode=ON 且自动清理过期 binlog,而 5.7 从库不识别 8.0 新增的 GTID 格式字段(如 source_id 扩展),解析失败后误判为缺失事件。
解决路径:
- 主库执行
SET GLOBAL gtid_mode = OFF_PERMISSIVE;,再SET GLOBAL gtid_mode = OFF;(需先确保enforce_gtid_consistency=OFF) - 主库设
binlog_format=ROW,并确认log_bin已启用 - 从库用传统 file/pos 方式配置复制:
CHANGE MASTER TO MASTER_LOG_FILE='mysql-bin.000001', MASTER_LOG_POS=154, ...,禁用MASTER_AUTO_POSITION=1 - 避免在主库执行
CREATE SERVER、INSTALL PLUGIN等5.7不支持的语句
如何检查主从两端的 GTID 兼容状态?
光看版本号没用,关键看运行时参数是否对齐。最直接的方法是分别在主从上执行以下命令比对输出:
SELECT @@gtid_mode, @@enforce_gtid_consistency, @@binlog_format, @@server_id;
常见不兼容组合:
- 主库
gtid_mode=ON,从库gtid_mode=OFF→ 复制无法启动(报错ERROR 3021) - 主库
binlog_format=STATEMENT,从库为8.0.23+→ 可能因函数不确定性被拒绝(如NOW()、UUID()) - 主库
server_id=1,从库也设为1→ 复制启动成功但数据不一致(GTID 冲突,Executed_Gtid_Set重复)
特别注意:8.0.30+ 引入 replica_parallel_type=LOGICAL_CLOCK,但 5.7 从库不支持该并发模式,必须设为 DATABASE 或关闭并行复制。
mysqldump 做跨版本从库初始化时的隐藏陷阱
用 mysqldump --single-transaction --master-data=2 导出 5.7 主库,再导入 8.0 从库,看似标准流程,但极易失败。原因在于 8.0 默认开启 sql_require_primary_key=ON,而 5.7 导出的建表语句不含主键时,导入直接报错;另外 8.0 移除了 mysql.plugin 表,若 dump 包含该表数据,会触发 ERROR 1305。
安全做法:
- 导出时加
--skip-triggers --skip-routines --skip-events,只导数据和基础 DDL - 导入前在
8.0从库临时执行SET SESSION sql_require_primary_key=OFF; - 手动过滤 dump 文件中的
CREATE TABLE `plugin`和INSERT INTO `plugin`行(用sed -i '/plugin/d') - 导入后立即执行
RESET MASTER;清空本地 GTID 记录,再用CHANGE MASTER TO ... MASTER_AUTO_POSITION=1;启动复制
跨版本复制没有银弹,版本差异带来的协议层、日志格式、权限模型变化,都可能在某个凌晨三点以一条诡异的 Slave_SQL_Running: No 形式爆发。最稳妥的方式,永远是让主从版本严格一致,或至少控制在官方明确标注“向后兼容”的小版本范围内(例如 8.0.33 主 + 8.0.32 从)。










