要求覆盖:半同步/组复制选型、切换判定、旧主隔离、数据补偿与回滚、切换后一致性校验。
题目:MySQL主从切换瞬间如何避免丢binlog与旧主双写?请设计可回滚的切换方案?
难度:high
标签:mysql/replication,mysql/ha
评分:⭐⭐⭐☆☆(3/5)
主从切换先要确认什么是丢 binlog 和旧主双写。丢 binlog 一般是新主已对外提供写入,但旧主还没提交滞留的 binlog,这部分就丢了;旧主双写是新主已提供服务,旧主还有写入请求,这里也会丢 binlog。核心是确保切换后恢复服务的时间,丢 binlog 要确保旧主同步完所有 binlog,但切换通常发生在旧主已经有问题时,一直等会扩大不可用,所以要划边界,通过重试、心跳确认旧主状态,并把切换期间产生的 binlog 全量转移;如果旧主已经不能服务,就放弃这部分 binlog。旧主双写则要确保切换前旧主不再提供写,双方通过协议关闭写入后再切换。
优点:正确拆出两种数据风险,并提出「先切断旧主写入再切换」的 fencing 方向。
不足:缺具体机制——半同步 AFTER_SYNC、GTID 集合判定位点、撤 VIP/read_only/KILL/STONITH 四层隔离;可回滚设计缺失(反向复制、回切路径、checksum 校验);旧主彻底挂掉后的补偿方案与可接受丢失窗口没提。
补充:优先 MHA/Orchestrator 自动切换 + 人工确认,或用 Group Replication 让共识层选主,减少脑裂。
切换安全的本质是「不产生两个可写主节点 + 不丢已向客户端承诺的数据」。丢数据有两种:旧主未同步的 binlog 未转移;旧主仍可写造成分叉。防丢靠半同步 AFTER_SYNC(保证客户端提交成功时至少一个从库收到)+ GTID 对齐;防双写靠 fencing:撤 VIP、set read_only=1、KILL 残留会话、必要时 STONITH 关机。
AFTER_SYNC 与 AFTER_COMMIT 的丢失/幻读差异AFTER_COMMIT 可能丢数据?——主库先提交再等 ACK,崩溃时从库可能没收到。pt-table-checksum。【一句话结论】 切换安全靠两件事:用半同步和 GTID 保证不丢已提交数据,用四层 fencing 保证旧主绝不能再写。
【三点展开】 第一,开启 AFTER_SYNC 半同步,客户端提交成功时至少一个从库已收到,切换时按 GTID 集合对齐,缺的部分用中继日志补偿。第二,切换前先隔离旧主:撤 VIP、设 read_only、杀会话,必要时直接关机,宁停勿双写。第三,保留旧主做反向复制,新主异常可回切,切换后跑 checksum 校验并配合业务对账。
【一句边界】 如果旧主彻底损坏,要明确「可接受丢失窗口」并写进 SLA,剩下的差异只能靠业务对账冲正,不能假装零丢失。