能跑通mysql 8.0异步主从复制的关键是:server-id唯一、log_bin启用、复制账号权限到位且认证插件匹配(mysql_native_password)、change replication source to坐标准确;漏任一环节,start replica即报错或静默失败。

MySQL 8.0 异步主从复制能跑起来,关键不在“配得多”,而在 server-id 唯一、log_bin 开启、复制账号权限到位、CHANGE REPLICATION SOURCE TO 的坐标准确——漏掉任意一个,START REPLICA 都会报错或静默失败。
主库必须确认的三项配置
别只改 /etc/my.cnf 就重启,改完要验证是否生效:
-
log_bin必须启用(MySQL 8.0 默认开启,但得用SHOW VARIABLES LIKE 'log_bin';确认值为ON) -
server-id必须是整数且全局唯一(比如主库设1,从库就不能再用1;若设成0或重复,复制线程直接拒绝启动) -
binlog_format强烈建议设为ROW(STATEMENT在含NOW()、UUID()等非确定函数时会导致主从数据不一致)
配置示例(追加到 [mysqld] 段):
server-id = 100 log-bin = mysql-bin binlog-format = ROW expire_logs_days = 7
改完执行 systemctl restart mysqld,再进 MySQL 执行 SHOW MASTER STATUS; —— 如果返回空结果,说明 log_bin 实际没开,不是配置写错就是没重启服务。
复制账号不能复用 root,且认证插件要匹配
MySQL 8.0 默认用 caching_sha2_password,但旧版客户端或某些从库连接可能不兼容。如果从库报 Authentication plugin 'caching_sha2_password' cannot be loaded,就得显式指定插件:
- 创建账号时用
IDENTIFIED WITH mysql_native_password(兼容性更好) - 必须授予
REPLICATION SLAVE权限,不是ALL PRIVILEGES - 主机名用
'%'要确保主库防火墙放行 3306,且bind-address没绑定死127.0.0.1
正确建号语句:
CREATE USER 'repl'@'%' IDENTIFIED WITH mysql_native_password BY 'ReplPass123!'; GRANT REPLICATION SLAVE ON *.* TO 'repl'@'%'; FLUSH PRIVILEGES;
之后在主库执行 SHOW MASTER STATUS;,记下 File 和 Position 值(例如 mysql-bin.000002 和 154),这两项后续必须原样填入从库命令。
从库启动复制前必须清空 relay log 并核对坐标
很多失败源于从库已有残留状态。执行 RESET REPLICA(MySQL 8.0.23+ 语法,旧版用 RESET SLAVE)清空所有复制元数据:
- 它会删除
relay-log.info、master.info和所有中继日志文件 - 接着用
CHANGE REPLICATION SOURCE TO重新指定主库地址和起始坐标(注意:SOURCE_LOG_FILE和SOURCE_LOG_POS必须与主库SHOW MASTER STATUS输出严格一致) - 最后
START REPLICA,立刻用SHOW REPLICA STATUS\G查看IO_Running和SQL_Running是否都为Yes
典型命令链:
RESET REPLICA; CHANGE REPLICATION SOURCE TO SOURCE_HOST='192.168.1.100', SOURCE_USER='repl', SOURCE_PASSWORD='ReplPass123!', SOURCE_LOG_FILE='mysql-bin.000002', SOURCE_LOG_POS=154; START REPLICA;
如果 IO_Running: No,先看 Source_IO_Error 字段——常见是网络不通、账号密码错、主库 skip-networking 开着;如果 SQL_Running: No,大概率是主从初始数据不一致(比如从库多了一张表),此时需重做全量同步。
验证复制是否真生效,别只信 “Yes”
SHOW REPLICA STATUS 显示两个 Yes 只代表线程在跑,不代表数据在同步。真正验证得靠数据:
- 主库建库
CREATE DATABASE testdb;,从库立刻SHOW DATABASES;看有没有 - 主库插入带时间戳的记录:
INSERT INTO t1 VALUES (NOW());,从库查该行时间是否一致(ROW格式下时间会精确复制) - 查
Seconds_Behind_Master—— 若长期 > 0,说明有延迟;若为NULL,通常是 SQL 线程卡住(比如遇到 DDL 冲突)
最容易被忽略的是:主库做了 DDL(如 ALTER TABLE),但从库对应表结构没提前准备好,SQL_Running 会停在错误位置,SHOW REPLICA STATUS 里 Last_SQL_Error 会明确提示缺失表或字段。这种问题不会自动恢复,必须人工干预。











