seconds_behind_master=0不代表无延迟,仅表示sql线程当前无滞后;真实追平需同时满足:io/sql线程运行中、sbm稳定为0、exec_master_log_pos最大(或gtid的retrieved与executed最接近),并确认“has read all relay log”。

不能“无缝”,但能最小化中断和数据丢失——前提是严格按验证→清理→重配→切流四步执行,跳过任一环节都可能双主写入或丢数据。
怎么确认哪个从库真能接替主库?
Seconds_Behind_Master = 0 不代表数据已全部回放,它只反映 SQL 线程当前延迟,relay log 可能还堆积未执行。
必须同时检查三项:
-
Slave_IO_Running: Yes 且Slave_SQL_Running: Yes(IO 和 SQL 线程都在跑) -
Seconds_Behind_Master: 0(不是 NULL,也不是波动值) -
Exec_Master_Log_Pos值最大(多个从库时比这个,它代表已执行到主库 binlog 的物理偏移)
更稳妥的做法:在候选从库上先执行 STOP SLAVE IO_THREAD,再反复 SHOW PROCESSLIST,直到看到 “Has read all relay log” 才算真正追平。若开启 GTID,则优先选 Retrieved_Gtid_Set 最全、且 Executed_Gtid_Set 与之最接近的节点。
STOP SLAVE 之后该用 RESET MASTER 还是 RESET SLAVE ALL?
非 GTID 模式下,必须用 RESET MASTER;GTID 模式下严禁执行,否则清空 gtid_executed,后续从库无法自动定位。
RESET SLAVE ALL 只删复制配置(如 master.info),不删 binlog 文件,也不重置 master_log_file 和 master_log_pos——其他从库 CHANGE MASTER TO 时会连错位点。
正确顺序是:
- 先
STOP SLAVE - 再
RESET MASTER(清空所有 binlog,新主从此记为mysql-bin.000001) - 手动删除
master.info和relay-log.info(防止 mysqld 重启后自动拉起旧复制)
注意:RESET MASTER 会彻底清空当前所有 binlog,务必确保原主库已离线,否则其他从库无法再同步增量。
my.cnf 里哪三项最容易漏改?
光改 server-id 不够,缺一不可:
- 取消注释或新增
log-bin = /path/to/mysql-bin(没 binlog 就不是主库) - 注释掉
read_only = ON(否则INSERT/UPDATE/DELETE全报Error 1290) - 注释掉
super_read_only = ON(MySQL 5.7+ 默认启用,比read_only更严格)
仅 SET GLOBAL 修改不持久,必须改配置文件并 systemctl restart mysqld。重启后验证:SHOW VARIABLES LIKE 'log_bin' 返回 ON,SELECT @@read_only 返回 0。
其他从库连新主时,位点参数为什么不能硬写?
别在 CHANGE MASTER TO 里写死 MASTER_LOG_FILE='mysql-bin.000001', MASTER_LOG_POS=154——新主刚 RESET MASTER 后,第一个事件位置未必是 154(尤其启用了 binlog_format = ROW 或有初始 GTID event)。
正确做法是:在新主上执行 SHOW MASTER STATUS,取回实时的 File 和 Position,再用于其他从库的 CHANGE MASTER TO。若原主库恢复需重新接入,强烈建议启用 GTID,直接用 SOURCE_AUTO_POSITION = 1,避免手动找位点出错。
真实故障中,最容易被忽略的是 super_read_only 的残留状态和 relay-log.info 文件未删——这两项会让新主看起来“能连上”,但实际拒绝任何写入,排查时往往卡在应用层报错,而非数据库日志。











