主从复制靠binlog和三个线程同步:主库binlog dump thread发送日志,从库io_thread拉取写入relay-log,sql_thread重放执行;必须开启binlog(row格式最佳),正确配置change master to坐标,sql线程报错需先修复再启动。

主从复制靠什么同步?就是 binlog + 三个线程
MySQL 主从复制不是魔法,核心就两样:主库的 binlog 日志,加上主从之间协作的三个关键线程。没有 binlog,复制根本启动不了;线程配不齐或卡住,同步就断在半路。
具体分工很清晰:
- 主库上一个
binlog dump thread:你执行START SLAVE后,它就上岗了,负责读取binlog并发给从库——注意,它读的时候会对对应日志段加锁,读完立刻释放,所以不影响主库写入 - 从库上两个线程:
IO_THREAD负责“收快递”,连接主库、拉取binlog events,写进本地relay-log;SQL_THREAD负责“拆快递+干活”,读relay-log、解析成 SQL 或行变更,再在从库重放 - 这三个线程缺一不可,
SHOW PROCESSLIST里能看到它们的状态。一旦IO_THREAD显示Connecting却连不上,或者SQL_THREAD停在Reading event from the relay log不动,基本就是同步卡住了
为什么必须开 binlog?而且格式不能乱选
主库不开 log-bin,等于没记账本,从库连“抄谁的作业”都不知道——START SLAVE 会直接报错 ERROR 1201 (HY000): Could not initialize master info structure。
更关键的是 binlog_format。别用默认的 STATEMENT,尤其涉及函数(如 NOW()、UUID())、自增主键、非确定性排序时,主从执行结果可能完全不同。
-
ROW模式最稳妥:记录每一行数据的前后镜像,从库重放的是“改了哪几行”,和主库执行路径无关 -
MIXED是折中,但实际行为难预测,线上建议统一用ROW - 改完
binlog_format必须重启 MySQL 生效(5.7 及以前),且所有从库也得保持一致,否则SQL_THREAD可能解析失败
change master to 的位置参数怎么填才不丢数据?
CHANGE MASTER TO 里的 MASTER_LOG_FILE 和 MASTER_LOG_POS 是从库同步的“起点坐标”。填错轻则跳过部分更新,重则主从数据永久不一致。
安全做法永远是:主库先 FLUSH TABLES WITH READ LOCK,再用 SHOW MASTER STATUS 拿到当前 File 和 Position,记下来;等从库配置好、START SLAVE 后,再 UNLOCK TABLES。
- 如果主库已运行很久、有大量写入,千万别凭空猜
mysql-bin.000001和120这种初始值 - 从库第一次启动前,若主库已有数据,必须先做一次全量备份恢复(如
mysqldump+source),再用SHOW MASTER STATUS的结果接续同步,否则增量部分对不上 -
MASTER_AUTO_POSITION=1可以绕过手动填 pos,但要求主从都开启 GTID,且版本 ≥ 5.6.5——不是万金油,别盲目启用
SQL_THREAD 报错中断后,为什么不能直接 start slave?
常见现象:SHOW SLAVE STATUS\G 里 Seconds_Behind_Master: NULL,SQL_THREAD 状态是 Slave_SQL_Running: No,Relay_Log_File 和 Relay_Log_Pos 停在某处,错误信息类似 Duplicate entry '123' for key 'PRIMARY'。
这时候直接 START SLAVE 不会恢复,因为冲突没解决,线程会立刻再次报错退出。
- 先确认错误是否可跳过:如果是主键冲突且业务允许忽略(比如双写导致),可用
SET GLOBAL sql_slave_skip_counter = 1(仅限STATEMENT模式)或STOP SLAVE; SET GTID_NEXT='xxx'; BEGIN; COMMIT; SET GTID_NEXT='AUTOMATIC'; START SLAVE;(GTID 模式) - 更推荐方式:查清冲突根源(比如从库被误写),人工修复从库脏数据,再
START SLAVE - 切记:跳过操作是临时补救,不是长期方案;频繁跳过说明主从权限控制或应用层写入逻辑有问题
真正容易被忽略的是 relay-log 的清理机制:relay-log 默认不会自动删,磁盘占满会导致 IO_THREAD 停摆。务必在从库配置 relay_log_purge=ON(默认开启),并定期检查 relay-log.index 和磁盘空间。











