mysql跨机房主从常“假同步”因网络延迟致半同步退化为异步,seconds_behind_master显示0但io线程卡在ack等待;mha切换易丢事务因脑裂和未校验同步完成;gtid双活不可行,须业务分片;pxc跨机房写性能骤降;须统一ntp时钟。

MySQL主从同步在跨机房场景下为什么经常“假同步”
因为网络延迟和半同步(rpl_semi_sync_master_enabled)的“确认”逻辑不等于数据真正落盘。跨机房链路丢包、RTT波动大时,semi-sync可能退化为异步,而监控看不出来——Seconds_Behind_Master仍显示0,但从库IO线程已卡在等待网络ACK。
实操建议:
- 必须启用
rpl_semi_sync_master_timeout并设为 ≤ 1000ms(默认10s太长),避免主库无限等待 - 用
SHOW STATUS LIKE 'Rpl_semi_sync_master_status'和Rpl_semi_sync_master_no_tx组合判断是否真实生效,单看Rpl_semi_sync_master_status是误导 - 不要依赖
Seconds_Behind_Master做故障切换决策,它只反映SQL线程延迟,不反映网络层积压
基于MHA做自动故障切换时,为什么新主库常丢事务
MHA本身不解决脑裂,跨机房网络分区(如IDC间专线闪断)时,原主库可能还在写入,而MHA已在备机房选出新主,导致双主写入、GTID冲突、甚至binlog被覆盖。
实操建议:
- 强制所有写请求走中间件(如
ProxySQL或MySQL Router),并在中间件层配置max_replication_lag熔断,超过阈值直接拒绝写入 - MHA切换前必须执行
SELECT MASTER_POS_WAIT(..., 3)等待所有已知事务同步到候选主库,超时则中止切换 - 禁用
log_slave_updates在从库上生成新binlog——否则MHA选出来的“新主”会把旧主的binlog再重放一遍,造成重复写入
GTID + 多源复制能不能撑起跨机房双活
不能。MySQL原生不支持跨机房双向同步下的冲突检测与自动合并。即使开了 gtid_mode=ON 和 enforce_gtid_consistency=ON,两个机房同时写同一张表,必然触发 ER_GTID_EXECUTED_RANGE_EXCEEDS_LIMIT 或 ER_MASTER_FATAL_ERROR_READING_BINLOG 错误,且无法自动恢复。
实操建议:
- 双活必须业务层分片:按用户ID哈希或城市划分写入归属机房,数据库只做单向同步(A→B 或 B→A),禁止双向
- 如果真要用多源复制(比如A机房同步B+C两个上游),务必关闭
replicate_same_server_id,否则同server_id的GTID会互相跳过 - 定期用
SELECT * FROM performance_schema.replication_applier_status_by_coordinator查看各通道状态,APPLYING_EVENT卡住比Seconds_Behind_Master更早暴露问题
用Percona XtraDB Cluster(PXC)替代主从?风险在哪
PXC本质是强一致的多写集群,但跨机房部署会放大写放大和网络敏感性。一个节点提交需多数派(quorum)确认,跨机房后RTT升高,wsrep_cert_deps_distance 指标飙升,事务重试率上升,最终表现为写吞吐骤降、连接堆积。
实操建议:
- 跨机房PXC只适合读多写少、且能容忍秒级写延迟的场景;写密集型业务必须收敛到单机房,其他机房只读
- 必须设置
gcache.size≥ 2GB(默认128MB),否则节点短暂断连后无法增量同步,只能全量SST,拖垮整个集群 - 监控
wsrep_local_send_queue_avg,持续 > 5 表示网络或磁盘已成瓶颈,此时切勿增加写负载
跨机房高可用最易被忽略的一点:没有统一的时钟源。NTP漂移超过50ms就可能导致GTID排序错乱、MHA误判主库存活。别只盯着MySQL参数,先用 ntpq -p 和 chronyc tracking 把时间对齐了再说。











