小树的架构笔记头像
关注

数据库跨中心同步:切换丢不丢数据,取决于你选的复制模式

摘要:两地三中心项目里,数据库的复制模式直接决定切换那天丢不丢数据。本文讲清楚同步、半同步、异步三种模式的真实差距,MySQL / Oracle 各自的落地选择,以及一份切换前可以直接核对的检查清单。

关键词:数据库同步、RPO、两地三中心、容灾切换、半同步复制、MySQL MGR、Oracle Data Guard


一、先讲一次「数据是怎么丢的」

某同城双活项目的切换演练,当天看起来非常成功:流量从 A 中心切到 B 中心,应用正常接管,监控全绿,现场甚至提前收了工。

第二天上午,财务对账报差异:切换时刻前后十几分钟的订单,在新库里查不到。

复盘时把复制链路的状态拉出来看,问题简单得让人后背发凉:

  1. 那套库用的是异步复制
  2. 切换当天正赶上业务高峰,主从延迟已经堆到几十秒;
  3. 切换脚本里没有「等待追平」这个动作,从库被直接提升为新主;
  4. 主库上已提交、还没传到从库的那段日志,随着主库一起下线了。

全程没有任何报错。数据库不觉得这是故障——它只是不知道自己不知道。

这件事给我的触动是:RPO 不是写在方案里的一行字,它是复制模式和切换流程共同决定的结果。 方案里写「RPO=5 分钟」很容易,切换那天到底丢不丢数据,看的是链路上每一层的具体配置。

二、三种复制模式,差的不只是延迟

先上对比表,用「一条事务的提交路径」来理解:

模式主库什么时候应答客户端极端情况丢多少代价
异步复制本地落盘即应答秒级到分钟级几乎零
半同步至少一个从库确认收到才应答极端情况丢一个事务延迟增加一个网络往返
全同步 / 组复制多数节点持久化后才应答零丢失(RPO=0)吞吐受最慢节点拖累

异步复制是所有数据库的默认选项,性能最好。主库把事务写进本地日志就应答客户端,从库「尽力而为」地追。一旦主库故障,没传过去的那部分数据就没了。适合日志类、统计类、丢了能从源头重放的业务。

半同步是折中项:主库提交前,至少要等一个从库确认「日志已收到」。但注意它的语义——极端情况下(比如唯一的从库恰好断开),半同步会退化为异步。所以它承诺的是「把丢失窗口压到极小」,而不是零。

全同步 / 组复制才是 RPO=0 的真正来源:事务必须被多数派节点持久化才算提交,主库故障时从库上必然有一份完整数据。代价是每个事务都要吃一次跨中心网络的往返延迟——这也是为什么它只在**同城裸光纤(1~2ms)**场景里现实,一旦放到异地(几十毫秒),每个事务都多等几十毫秒,吞吐直接崩掉。

一个经常被忽略的认知:RPO=0 的成本单位不是钱,是延迟。物理距离就是 RPO 的天敌。

三、Oracle 和 MySQL 各自怎么落

Oracle:Data Guard 三种保护模式

保护模式传输方式RPO特点
最大保护同步(SYNC)0灾备端不可用时,主库直接停写
最大可用平时同步,故障自动降级异步平时 0核心账务的常见选择
最大性能异步秒级默认,最常见

「最大保护」听起来最好,但它把灾备端变成了主库的单点:灾备端一抖,主库就拒绝写入。所以工程上更常见的是「最大可用」——平时同步保零丢失,灾备端故障时自动降级为异步保住主库,恢复后再追平。

MySQL:从主从到 MGR

  • 主从 + 增强半同步:多数业务库的甜点位。注意用增强半同步(AFTER_SYNC,先等从库确认、再本地提交),而不是老的 AFTER_COMMIT——前者才是真正的无损语义。
  • MGR(组复制):内置 Paxos 类协议,事务要经过组内多数派确认才提交;单主模式下主库故障自动选主,切换不需要人工介入。
  • 真实两个 DC 的落地选择:RPO=0 的主通道放在数据库同步层(MGR / RAC Extended 一类),同城裸光纤直连、往返延迟 1ms 级,实测下来 MGR 表现稳定;底层存储的跨中心双活只做兜底。

这里呼应一下前面聊过的取舍(《集中式 vs 分布式存储:数据库场景怎么选》里详细算过账):数据库同步做 RPO=0 主通道、存储双活做兜底。两层都压上同步复制,脑裂窗口和一致性校验成本直接翻倍,多数团队扛不住这个复杂度。

四、选模式之前,先给库分级

不是每个库都值得 RPO=0。

业务分级典型系统建议模式RPO 目标
核心账务 / 交易支付、订单、账务全同步 / 组复制(同城)0
一般业务库CRM、运营后台增强半同步秒级
日志 / 报表 / 缓存行为日志、统计明细异步分钟级,可重放

反例也见过:为了「统一标准」给所有库都上组复制,硬件翻倍、运维复杂度翻倍,换来的 RPO 改善对日志类业务毫无意义——它们本来就能从上游重放。

五、模式选对了,切换流程照样能毁掉 RPO

三个关键动作,缺一不可。

1. 等追平,再提升

切换脚本里必须有「复制延迟归零」的判定(MySQL 侧用 GTID 等待,如 WAIT_FOR_EXECUTED_GTID_SET;传统主从看 Seconds_Behind_Master 和中继日志是否回放完)。而且要设超时熔断:追不平就中止切换、转人工,而不是硬切。

2. 先隔离旧主(fencing)

新主提升之前,旧主必须先被断写(置只读、撤 VIP、或集群层面直接隔离)。顺序错了,应用一重连把数据写回旧主,两边数据分叉,这比丢数据更难收场。很多「双活变双主」的事故,根因都是 fencing 没做或者做晚了。

3. 连接路由告诉应用去哪找新主

VIP 漂移、ProxySQL 一类中间件、或者域名切换,三选一。原则是切换时不改应用配置——这件事在《两个数据中心一套 DNS:用 Anycast 把双活流量收敛到一个 IP》里展开过,数据库同样是「认路不认 IP」。

六、一个隐秘的坑:保护性降级

半同步有个「贴心」设计:从库 ACK 超时(默认 10 秒),自动降级为异步,保住主库的可用性。

但换个角度看,这个降级就是 RPO 从秒级悄悄变成分钟级的通道。高峰期网络一抖、从库回放一慢,降级发生了,没有任何人会知道——除非你专门盯着它。

所以半同步架构里,「退化为异步」这个事件本身必须有独立告警。另外这几个延迟来源值得重点盯:大事务(一次批量 DELETE 顶平时十分钟的增量)、批量 DDL、从库回放瓶颈、跨中心链路抖动。

七、切换前检查清单(可直接抄)

检查项通过标准风险等级
复制模式与业务分级匹配:核心全同步、一般半同步、日志异步🔴 高
追平等待切换脚本含延迟归零判定 + 超时熔断🔴 高
旧主隔离fencing 自动化,先隔离旧主、再提升新主🔴 高
连接路由VIP / 中间件 / 域名三选一,切换不改应用配置🟡 中
降级告警半同步退化异步、复制中断,两者都有独立告警🟡 中
延迟监控主从延迟阈值告警,高峰期重点盯🟡 中
演练后对账切换演练收尾固定跑一次核心表对账🟢 低

最后一条是教训换来的:开头那次「丢十几分钟订单」,如果演练收尾固定有对账动作,问题当场就能暴露,而不是等财务第二天找上门。

八、写在最后

到这里,容灾系列的四个层面都聊过了:存储层(集中式 vs 分布式怎么选)、数据库层(本文)、应用层(无状态化)、网络层(统一 DNS)。倒过来读也成立:先让业务认路(DNS),再让应用能漂(无状态),数据库跟上(复制模式),存储兜底(双活)。

一句话总结本文:RPO 是设计出来的,不是采购来的。 复制模式选型、切换流程、降级告警,每一环都不能指望「上了双活就万事大吉」。

你遇到过切换后丢数据吗?最后是怎么定位的?评论区聊聊。


(本文为「小树的架构笔记」技术线原创内容,基于真实项目经验与公开架构实践整理,未引用客户交付物。)


本文出自「小树的架构笔记」——两个数据中心云平台的一线运维经验,持续更新。
📎 同名公众号回复【架构】,领《DC 架构实战笔记》(两地三中心 / 存储选型 / DNS 双活 / 无状态化 合集)。

「DC 云平台架构实战」系列

  1. 《两地三中心不是画图:业务系统承载的 3 个真实取舍》
  2. 《集中式 vs 分布式存储:数据库场景怎么选》
  3. 《两个数据中心一套 DNS:用 Anycast 把双活流量收敛到一个 IP》
  4. 《应用无状态化:容灾切换前必须拆掉的第一颗雷》
  5. 《数据库跨中心同步:切换丢不丢数据,取决于你选的复制模式》(本文)

转载自 CSDN-专业IT技术社区

原文链接:https://blog.csdn.net/shuye1116/article/details/164507387

文章来源转载

评论

赞0

评论列表

微信小程序
QQ小程序

关于作者

点赞数:0
关注数:0
粉丝:0
文章:0
关注标签:0
加入于:--