mysql主从复制中服务器的版本兼容性问题与解决

3次阅读

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

mysql主从复制中服务器的版本兼容性问题与解决

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 STATUSG 中若出现 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 SERVERINSTALL PLUGIN5.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 从)。

text=ZqhQzanResources