主库必须开启 binlog 且设置唯一 server-id
MySQL 主从复制依赖 binlog 记录写操作,如果
my.cnf中没启用
log-bin,从库连日志都拉不到,复制必然失败。同时,
server-id必须是整数且主从不能相同——哪怕只是临时测试,设成
1和
2最稳妥。
常见错误:只加了
log-bin=mysql-bin却漏掉
server-id,或两个实例用了同一个
server-id=1,此时执行
START SLAVE会静默失败,
SHOW SLAVE STATUS\G里
Seconds_Behind_Master为
NULL,
Slave_IO_Running显示
No,但错误日志里可能只有一行
Could not find first log file name in binary log index file,容易误判为日志文件丢失。
建议配置段示例:
[mysqld] server-id = 1 log-bin = mysql-bin binlog-format = ROW skip-slave-start = 1
从库需用主库的 binlog 文件名和 position 手动指定同步起点
不是所有场景都能用
mysqldump --master-data自动带出位置信息;如果主库已有数据、又没锁表导出,就得靠
SHOW MASTER STATUS查当前日志名和偏移量,再在从库执行
CHANGE REPLICATION SOURCE TO(MySQL 8.0.23+)或旧版
CHANGE MASTER TO手动对齐。
关键点:
SOURCE_HOST填主库可被从库访问的 IP 或域名,不是
127.0.0.1
SOURCE_LOG_FILE和
SOURCE_LOG_POS必须严格匹配
SHOW MASTER STATUS输出的
File和
Position账号需有
REPLICATION SLAVE权限,不能只给
SELECT
执行示例(MySQL 8.0.26):
CHANGE REPLICATION SOURCE TO SOURCE_HOST='192.168.1.10', SOURCE_USER='repl', SOURCE_PASSWORD='p@ssw0rd', SOURCE_LOG_FILE='mysql-bin.000003', SOURCE_LOG_POS=154;
启动复制后务必检查两个线程状态和延迟
START REPLICA(或旧版
START SLAVE)只是发起指令,不代表复制已正常运行。必须立刻查
SHOW REPLICA STATUS\G(MySQL 8.0.22+)或
SHOW SLAVE STATUS\G,重点盯住三项:
Replica_IO_Running:对应拉日志的 I/O 线程,
Yes才说明网络通、账号对、日志可读
Replica_SQL_Running:对应回放日志的 SQL 线程,
Yes表示解析和执行无阻塞
Seconds_Behind_Master:非
NULL且数值稳定下降才算真正追上;若长期为
0但
Replica_SQL_Running是
No,大概率是某条语句执行报错卡住了
遇到 SQL 线程停摆,先看
Last_SQL_Error字段,常见如主从表结构不一致、从库有写入导致主键冲突、或者启用了
read_only=1但忘了给复制账号加
SUPER权限(MySQL 5.7 及以前)。
ROW 格式比 STATEMENT 更可靠,但要注意主从版本兼容性
用
STATEMENT格式时,像
NOW()、
UUID()、
INSERT ... SELECT这类非确定性语句,在从库重放可能结果不同,引发数据不一致。默认选
ROW能规避这类问题,但要注意: MySQL 5.6 从库无法识别 5.7+ 写入的 row-based 日志(因新增字段),主从版本差一个大版本就可能同步中断
binlog-row-image=FULL(默认)会记录整行变更,安全但日志体积大;
MINIMAL节省空间,但要求主从表结构完全一致,否则从库解析失败 如果主库开了
innodb_autoinc_lock_mode=2(交错模式),而从库是 5.7 以下,AUTO_INCREMENT 值可能不一致
生产环境建议主从 MySQL 小版本号尽量一致,至少保证大版本相同,比如都是 8.0.x。
主从复制不是一劳永逸的事,最常出问题的地方不在搭建过程,而在后续主库结构变更(如
ALTER TABLE)、从库意外写入、或网络抖动后 IO 线程没自动重连——这些都需要监控脚本或定期人工核对
Seconds_Behind_Master和线程状态。
