mysql 5.7 主库 → mysql 8.0 从库是唯一可行路径,反向必然失败;因8.0可解析5.7的row binlog事件,而5.7无法识别8.0新增系统表、caching_sha2_password插件及原子ddl日志格式。

主从复制不能“反向运行”:MySQL 5.7 主库 → MySQL 8.0 从库是唯一可行路径,反过来必然失败。这不是配置技巧问题,而是 8.0 的 binlog 解析器能向下兼容 5.7 的 ROW 事件,而 5.7 根本不认识 8.0 新增的系统表结构、caching_sha2_password 握手协议和原子 DDL 日志格式。
为什么 START SLAVE 启动后 Seconds_Behind_Master 一直是 NULL
这不是延迟高,是 IO 线程压根没连上主库——最常见原因是认证插件不匹配。8.0 从库尝试用 caching_sha2_password 去连 5.7 主库,但 5.7 不提供该插件元数据,握手直接中断。
- 立刻查 8.0 从库错误日志,搜
Authentication plugin 'caching_sha2_password' reported error或Could not execute Write_rows_v1 event on table mysql.user - 在 5.7 主库的
my.cnf中强制加:default_authentication_plugin=mysql_native_password,并重启 mysqld - 所有用于复制的账号必须显式用该插件创建:
CREATE USER 'repl'@'%' IDENTIFIED WITH mysql_native_password BY 'xxx'; - 禁止在 5.7 主库执行
ALTER USER ... IDENTIFIED WITH caching_sha2_password,否则后续任意一条 binlog 都会让 8.0 从库 SQL 线程卡死
mysqldump 全量导入后 START SLAVE 报错的隐藏原因
导出时没关 GTID、没清空从库自身 GTID 状态、系统库污染,三者任一都会让复制启动失败,且错误信息非常隐蔽(比如报 Unknown system table 却不指明哪张表)。
- 5.7 主库导出必须加
--set-gtid-purged=OFF,否则 dump 文件里硬编码了旧 GTID,8.0 导入后无法对齐 - 8.0 从库导入完成后,立刻执行
RESET MASTER,清空gtid_purged,避免与主库 GTID 集合冲突 - 绝对不要导入
mysql库——5.7 的mysql.user表含password字段,8.0 已改为authentication_string;导入会破坏权限系统,甚至导致 mysqld 启动崩溃 - 启动前确认主库
binlog_format=ROW(5.7 默认已是),且gtid_mode=OFF;官方明确不支持跨版本 GTID 复制
切换前最容易跳过的三步物理一致性验证
看到 Seconds_Behind_Master = 0 就切流量?危险。这个值只说明 SQL 线程追到了中继日志末尾,不代表数据行级一致。
- 用
pt-table-checksum对比主从大表(如订单、日志)的校验和,尤其注意chunk_size要调小,避免锁表太久 - 在原 5.7 主库执行
FLUSH TABLES WITH READ LOCK;后,立刻记下SHOW MASTER STATUS的File和Position,这是切换的精确位点 - 检查 8.0 从库的
SHOW SLAVE STATUS\G:确保Retrieved_Gtid_Set和Executed_Gtid_Set完全为空(因为已关 GTID),且Relay_Master_Log_File和Exec_Master_Log_Pos与主库File/Position严格一致
真正麻烦的不是某条命令写错,而是参数修改必须两端同步生效:主库改了 default_authentication_plugin,但从库若还开着 ONLY_FULL_GROUP_BY,遇到带分组的 binlog 事件照样卡在 SQL 线程——每个参数都是链式依赖,漏一个就断在看不见的地方。











