binlog 是主库的“操作录像带”,必须开启才能复制
主库不写
binlog,从库就完全收不到任何变更——这是主从复制的硬性前提。它不是可选功能,而是整个复制链路的源头。MySQL 默认关闭
binlog,必须显式配置
log-bin=binlog(文件名可自定义)并重启生效。常见错误是只改了配置但忘了重启 mysqld,结果
SHOW VARIABLES LIKE 'log_bin';仍返回
OFF,同步必然失败。
另外,
binlog_format推荐设为
ROW:它记录每一行数据的实际变化,避免
STATEMENT模式下因函数(如
NOW()、
UUID())或非确定性语句导致主从数据不一致。虽然日志体积变大,但数据一致性有保障,生产环境几乎无例外。
relaylog 是从库的“本地待办清单”,由 IO 线程写入
从库的
IO_THREAD连上主库后,会持续拉取
binlog内容,并原样写入本地的
relay-log文件(如
relay-bin.000001),这个过程不解析、不执行,只是搬运。关键点在于:
relay-log不是永久存储,而是中转站——一旦
SQL_THREAD执行完某段日志,对应内容就会被自动清理(除非手动配置
relay_log_purge=OFF)。
常见误操作是直接删
relay-log文件。这会导致
SQL_THREAD找不到执行位置而报错
Could not parse relay log event entry。正确做法是用
RESET SLAVE(清空所有中继日志 + 重置复制坐标)或
RESET SLAVE ALL(额外清除
master.info等元数据)。
两个日志的生命周期和角色完全不同
binlog在主库上长期保留(受
expire_logs_days控制),既用于复制,也用于备份恢复(
mysqlbinlog回放);而
relay-log只存在于从库,纯属复制中间产物,生命周期由 SQL 线程推进进度决定。
它们还分属不同线程管理:
binlog由主库的
Binlog Dump Thread向外推送;
relay-log由从库的
IO_THREAD接收写入,再由
SQL_THREAD读取执行。如果
SHOW SLAVE STATUS\G中看到
Seconds_Behind_Master持续增长,大概率是
SQL_THREAD执行慢(比如大事务、锁争用),而不是网络或
IO_THREAD问题。
查日志时别搞混命令和路径
看主库
binlog:用
mysqlbinlog /var/lib/mysql/binlog.000001(路径以
datadir和
log_bin配置为准);
看从库
relay-log:同样用
mysqlbinlog /var/lib/mysql/relay-bin.000001,但要注意文件名前缀由
relay_log参数定义,默认是
relay-bin;
查当前坐标:主库用
SHOW MASTER STATUS;,从库用
SHOW SLAVE STATUS\G中的
Relay_Master_Log_File和
Exec_Master_Log_Pos—— 这俩才是实际已执行到主库 binlog 的位置,不是
Relay_Log_File和
Relay_Log_Pos(那是中继日志自身偏移)。
最容易忽略的是:
relay-log的索引文件(如
relay-bin.index)必须和日志文件保持一致,否则启动时可能找不到最新文件,导致复制中断。这个文件不能手动编辑,全靠 MySQL 自动维护。
