主库必须设非零唯一server-id并开启log-bin,否则START SLAVE后IO_Running必为No;从库也须设唯一server-id但不可开log-bin(级联除外);binlog_format推荐强制设为ROW并重启生效。

主库必须设 server-id 且开启 log-bin
不满足这两条,复制直接启动失败——START SLAVE 后 IO_Running 必为 No,错误日志里大概率出现 Could not find first log file name in binary log index file。这不是权限或网络问题,是根本没日志可拉。
实操建议:
-
server-id必须是非零整数,且在同局域网内全局唯一;主库设server-id = 1,从库就不能再用1,也不能和其他从库重复(比如2、3) -
log-bin路径建议写绝对路径,例如log-bin = /var/lib/mysql/mysql-bin,避免 MySQL 启动时因工作目录不确定导致日志文件创建失败 - 修改配置后必须重启 MySQL:
systemctl restart mysql,仅 reload 不生效 - 验证是否生效:连上 MySQL 后执行
SHOW VARIABLES LIKE 'log_bin';(返回ON)和SHOW VARIABLES LIKE 'server_id';(返回你设的数字)
binlog_format 推荐设为 ROW,别用 STATEMENT
用 STATEMENT 格式时,像 NOW()、UUID()、自增主键、触发器等操作,在从库重放可能产生不一致。比如主库插入一条带 NOW() 的记录,从库执行时时间戳就不同了;更严重的是某些函数在从库不可用,直接导致 SQL_Running: No。
实操建议:
- 在主库配置文件中明确指定:
binlog_format = ROW - MySQL 5.7+ 默认已是
ROW,但旧版本或 Docker 镜像常默认MIXED或STATEMENT,不能依赖默认值 - 改完需重启 MySQL,且该参数不能动态设置(
SET GLOBAL binlog_format = 'ROW'在运行时无效) - 如果已用
STATEMENT同步了一段时间,切到ROW前建议先停写、清空 relay log、重做全量同步,否则格式切换点附近易出错
从库也要配 server-id,但不能开 log-bin(除非做级联)
从库没设 server-id,CHANGE MASTER TO 会成功,但 START SLAVE 后 IO_Running 立刻变 No,错误提示常为 Client requested master to start replication from impossible position——本质是 MySQL 拒绝为无 ID 的实例建立复制连接。
实操建议:
- 从库
server-id必须与主库及其他从库不同,例如主库是1,从库可设2、101等 - 普通从库**不要**配置
log-bin;开了又不用于级联,只会多占磁盘、拖慢性能,还可能因日志轮转策略干扰主从状态判断 - 只有要作为“中间主库”(即一主多从中的某台从,还要再同步给下一级从)时,才需同时设
server-id和log-bin - 从库配置改完一样要重启 MySQL,不能只靠
SET GLOBAL
配置文件位置和权限容易被忽略的细节
很多人改了 /etc/my.cnf 却没生效,是因为 MySQL 实际读的是另一个配置文件,比如 /etc/mysql/mysql.conf.d/mysqld.cnf(Ubuntu/Debian)或 /usr/my.cnf(部分编译安装)。还有人把配置写在 [client] 段下,结果 log-bin 完全不加载。
实操建议:
- 先查 MySQL 实际加载了哪些文件:
mysqld --verbose --help | grep "Default options" - 所有服务端配置(
log-bin、server-id、binlog_format)必须放在[mysqld]段内,不能放在[client]或[mysql] - Docker 场景下,挂载的配置文件需确保容器内 MySQL 进程有读取权限(常见坑:
chown 999:999 my.cnf,因为 MySQL 容器默认以用户mysql(UID 999)运行) - 配置文件本身权限建议
644,避免因600导致 MySQL 启动时报File not readable
配置真正生效的关键不在命令多酷炫,而在三个地方都对齐:主库的 log-bin 和 server-id、从库的 server-id、以及两者 binlog_format 一致。漏掉任意一个,SHOW SLAVE STATUS\G 里的 Seconds_Behind_Master 就永远是 NULL。











