主从切换前必须确保Seconds_Behind_Master稳定为0至少30秒,检查IO/SQL线程均为Yes,用pt-heartbeat校验延迟,停写前断开所有客户端连接,旧主执行RESET SLAVE ALL后重配复制,DNS切换需预热并规避缓存问题。

主从切换前必须验证 Seconds_Behind_Master 为 0
从库延迟没追上就切,业务立刻丢数据。不是“接近 0”,是监控里稳定显示 0 至少 30 秒以上。
常见错误现象:SHOW SLAVE STATUS 里 Seconds_Behind_Master 忽高忽低,或卡在 NULL(说明 IO/SQL 线程异常);这时切过去等于把断点当起点。
- 先检查
Slave_IO_Running和Slave_SQL_Running都是Yes - 用
pt-heartbeat比Seconds_Behind_Master更准,尤其跨机房场景 - 如果延迟大,别硬等,先查慢日志、主库写入突增、从库磁盘 I/O 压力
停写主库前要确认所有客户端已断开连接
MySQL 不会自动踢掉活跃连接,FLUSH TABLES WITH READ LOCK 只阻塞新写入,老连接还在跑 UPDATE/INSERT,一释放锁就写回旧主,造成双写分裂。
使用场景:你执行了 STOP SLAVE 和锁表,但应用层连接池没回收,或者长连接还在发事务。
- 用
SELECT * FROM performance_schema.threads WHERE TYPE = 'FOREGROUND'查活跃会话 - 配合
KILL主动终止非系统线程(注意避开system_user或复制线程) - 更稳妥的做法是提前在代理层(如 ProxySQL、HAProxy)下线主库节点,再操作
RESET SLAVE ALL 必须在旧主上执行,而不是新主
切完后旧主转从库,很多人顺手在新主上执行这个命令,结果清掉了新主的 master.info,导致它无法再作为主库被其他从库连——因为 binlog 位置信息丢了。
参数差异:RESET SLAVE 只清复制元数据;RESET SLAVE ALL 还删 relay-log.info 和中继日志文件,更适合彻底重置角色。
- 旧主转从库时,在旧主上执行
RESET SLAVE ALL,再CHANGE MASTER TO ...指向新主 - 新主不需要、也不应该执行该命令
- 执行前确保
relay_log_purge = ON(默认),否则中继日志残留可能撑爆磁盘
业务 DNS 切换比 VIP 漂移更容易出问题
DNS 缓存不可控,TTL=30s 不代表客户端 30 秒内一定刷新,Java 应用默认缓存 DNS 5 分钟(networkaddress.cache.ttl),Go 默认永久缓存(除非显式设 GODEBUG)。
性能影响:VIP 方案需 keepalived + ARP 刷新,网络层生效快;DNS 方案依赖客户端行为,故障窗口难收敛。
- 如果必须用 DNS,应用启动时加
InetAddress.getByName(...)预热 + 定期刷新逻辑 - 数据库连接串里避免写死域名,改用配置中心下发 IP 或短 TTL 域名
- 切完立刻验证:从应用机器
dig +short your-db.example.com,别只信本地nslookup
真正麻烦的不是命令怎么敲,是那些没打印在日志里的连接、缓存和中间件状态——它们不会报错,只会悄悄把数据写到错误的地方。










