“你们这个主备,到底能不能在关键时候顶上去?”——这句话我几乎每次给客户做达梦数据库架构评审都会被问到。DM数据库的实时主备集群确实能扛住单点故障,但“能扛”和“真正验证过能扛”是两码事。很多团队把主备部署完毕、监视器一切正常就当成交付完成,结果等到生产环境真出问题那天,才发现备库日志断档、监视器权限不对、切换脚本早就不兼容了。
所以这一篇我打算聊聊怎么对DM数据库的实时主备做一次完整的故障模拟演练:从架构原理、演练设计,到具体制造故障、切换、恢复的全过程,以及我踩过的那些坑。这篇更适合生产环境已经跑着DM双机、或者正在做主备方案选型的DBA和架构师,看完之后你应该能照着设计出自己的演练方案。
1. 故障演练前必须搞清楚的架构基础
1.1 DM主备到底是怎么工作的
先说底层机制。DM数据库的主备同步核心是redo日志的传输与重做。每次事务提交产生redo日志后,主库通过MAL系统将日志实时或异步地发送给备库,备库收到日志后进行重做,从而保持数据一致。达梦在这之上又构建了一套完整的守护体系,关键组件有三个:
- 主库(Primary):对外提供读写服务,所有业务写入都走主库。
- 备库(Standby):持续接收并应用主库的redo日志,保持热备状态。
- 守护进程(dmwatcher)和监视器(dmmonitor):守护进程负责监控本机数据库状态,监视器则负责协调整个集群的切换决策。
这里有个容易混淆的点:主备自动切换并不是数据库进程自己直接决定的,而是监视器在确认“主库不可用”之后,向备库下发切换命令。所以演练时你不仅要在数据库层面制造故障,还要观察监视器和守护进程的联动是否正常——很多主备集群“假正常”的问题就出在这条联动链路上。
1.2 实时主备与异步备机的差异
很多人在部署之前没想清楚业务到底需要哪种同步模式,结果演练时才发现数据丢失容忍度与同步模式不匹配。达梦实时主备的核心特征是事务在主库上提交时,redo日志已经同步到备库并完成归档接收,因此主库发生故障时理论上可以做到不丢数据,但代价是每次事务提交都有同步等待的开销,业务高峰期主库响应时间会变长。
异步备机则是主库本地提交完成后立即返回,日志异步发送到备库,性能影响小但故障时数据丢失窗口不可控。如果需要“零丢失”的业务场景(比如订单库、账户流水),必须选择实时主备;如果只是做历史库、报表库的容灾,异步备机就足够了。这一点在演练前面一定要和业务方对齐,否则切换之后两边会对“数据到底丢没丢”产生很大分歧。
1.3 演练目标:故障转移与计划内切换是两条路
故障模拟不是只验证“备库能不能变成主库”,而是要区分两类切换路径:
- 计划内切换(switchover):主库本身没坏,通过手动指令将主备角色互换。常用于机房维护、操作系统升级、数据库版本原地更新等场景。
- 故障转移(takeover/failover):主库真正宕机或服务不可用,备库被动接管成为新的主库。
在DM监视器里,这两条路径对应的指令并不相同,自动故障转移还需要确认监视器是否配置了自动切换权限。演练的时候,我建议两条路径都覆盖,先做计划内切换验证日常维护能力,再做故障转移验证应急能力,顺序不要反,因为计划内切换能先把正常流程跑通,故障转移更有针对性。
2. 怎么设计一次真实有效的故障演练
2.1 先画清楚拓扑和职责边界
我见过不少演练翻车的案例,起因不是操作复杂,而是连“谁是主、谁是备、监视器在哪台机器”都没在演练方案里写清楚。这里我给出一个常见的DM实时主备拓扑示例,你演练前可以照着整理自己的:
角色安排建议如下:
- 主库主机:192.168.1.10,实例名GRP1_RT_01,数据库服务dmserver。
- 备库主机:192.168.1.11,实例名GRP1_RT_02,数据库服务dmserver。
- 独立监视器主机:192.168.1.12,运行dmmonitor工具。
- 数据目录:/dm/data,归档目录:/dm/arch,守护进程配置文件dmwatcher.ini,监视器配置文件dmmonitor.ini。
这里要特别提醒一点:监视器最好放在第三台独立主机上,不要和主库或备库放在一起。如果监视器和主库同机,主库宕机时监视器也可能跟着不可用,自动切换就会失灵。这也是很多生产事故“备库明明活着却始终没人接管”的根源之一。
2.2 明确演练的通过标准
演练不能只为了“跑一遍流程”,每个环节都应该有明确的通过标准,否则演练结束后没办法判断主备集群是否真的合格。我自己常用的通过标准是这样几条:
- 主库故障发生后,监视器能在设定的超时时间内检测到异常,并在可接受的时间窗口内自动完成备库角色升级。
- 切换后新旧主库的数据经过校验保持一致,或者偏差在业务可接受范围内(取决于你用的是实时主备还是异步备机)。
- 应用在更新数据库连接配置或者连接池自动重连之后,能够正常读写新主库。
- 原主库恢复后,能重新以备库身份加入集群,数据追平,不再影响集群健康状态。
这些标准最好在演练开始之前打印出来发给所有参与人,演练结束后逐条打钩,不要凭感觉说“感觉还行”。
2.3 演练前的准备清单
准备阶段如果偷懒,演练现场就会出各种低级问题。我这里列一份完整的准备清单:
- 确认主备库都有最新的物理备份,并保留备份文件在独立存储,避免演练过程中意外操作导致数据不可恢复。
- 检查归档日志连续性,确保备库接收日志无中断,可以通过dmmonitor的show health命令查看归档状态。
- 确认监视器能正常登录,并且监视器配置里已经指定了自动故障切换的权限。
- 检查所有主机的时间同步,时间偏差过大会导致心跳超时误判,这是主备集群最常见却最容易被忽略的坑。
- 在业务低峰期操作,并通知相关研发、测试、运维同事,避免演练过程中有人连接数据库执行DDL造成额外干扰。
这份清单我每次演练都会检查一遍,如果你发现备库归档断档,那就先把断档问题解决,否则故障转移后大概率丢数据。
3. 故障模拟实操全过程
3.1 场景一:模拟主库实例崩溃(进程级故障)
这是最直接的故障模拟方式,适合验证监视器对实例异常退出的识别和自动切换能力。我通常选择直接kill掉主库的dmserver进程,模拟类似OOM被杀或后台进程崩溃的情况。操作建议先登录主库主机,确认当前主库状态,再执行kill命令,然后立刻转向监视器观察日志。
需要注意一点:建议一步一步来,不要一开始就模拟拔网线之类的高级故障。先把最简单的实例崩溃跑通了,再往复杂场景推进。
3.2 场景二:模拟主库主机宕机或网络隔离
实例崩溃测试通过后,我再升级难度:模拟主库主机掉电或者网络隔离。这一步验证的不只是数据库守护逻辑,还包含监控网络、系统层的心跳检测。具体做法可以用防火墙将主库的数据库服务端口、MAL通信端口全部丢弃,或者直接关机,观察监视器的检测行为。
这个场景最大的价值在于验证故障发生的“不可预知性”。实例崩溃还会在系统日志里留下明确的退出痕迹,而网络隔离时主库本身还在运行,心跳消息发不出去,守护进程和监视器只能依靠超时机制来判定故障,这中间需要一定的判定时间,这个时间是RTO的一部分,必须在演练前和业务方说清楚。
3.3 触发主备切换并观察角色变化
当监视器确认主库不可用后,会自动下发切换指令。如果你配置的是半自动模式,则由DBA在监视器里手动执行切换指令。无论哪种模式,切换过程中都应该重点观察这几个状态变化:
- 备库实例状态从Mount/Standby变为Open/Primary。
- 新主库开启对外读写服务,且继续保留归档日志记录。
- 监视器日志中出现切换相关的记录,并更新集群拓扑。
这里我要特别强调一点:不要只盯着数据库看,还要看应用能不能连上。很多演练到此就结束了,但实际业务不会自动切过去——你还要处理数据库连接地址、连接池配置、业务系统的数据源切换等问题。如果是生产环境,建议提前将应用的数据源配置支持多地址Failover,或者通过VIP漂移方案屏蔽后端变化。
3.4 切换过程中的常见干预时机
切换开始后,我通常会忍住不手动干预,除非出现以下情况:备库数据不完整且不能接管,需要临时挂载原主库进行紧急恢复;监视器未检测到故障导致自动切换长时间未执行,需要手动触发;业务要求回切原主库,需要终止切换流程。演练时最好提前约定一个“谁有权干预”的规则,避免多人同时登录监视器操作,产生指令冲突。
4. 切换后的验证与故障恢复
4.1 数据一致性验证
主备切换完成,不等于演练结束。数据一致性验证是演练中最容易敷衍的一环,但也是业务方最关心的部分。我建议至少做三件事:
- 登录新主库,查询关键业务表的记录数、最新时间戳,与切换前记录的基准数据进行比对。
- 如果主备集群里还有其他备库,确认所有剩余备库能够继续同步新主库的redo日志,不被“落下”。
- 使用达梦的日志分析手段,检查切换期间是否存在未传送到备库的日志记录,判断数据丢失窗口。
如果用的是实时主备且操作规范,结果大概率是零丢失。但“大概率”不代表“一定”,只有通过数据比对,你才能在演练报告里给业务方一个确定的答复。
4.2 原主库重新加入集群
模拟演练中,原主库并不是真的损坏,只是被我们人为制造了故障。演练后期必须原主库重新加入集群,否则集群长期处于单点状态,后续再出问题就没有退路了。
原主库重新加入集群的操作逻辑是:先将原主库以Standby模式启动,再从新主库重新同步数据,最后确认日志追平并转换为正常的备库。这里有一个经常出错的细节:不要用旧配置直接启动,否则原主库可能因为你没清理旧的守护配置,启动后仍然试图以主库身份运行,导致集群脑裂。我个人习惯是在启动之前先检查dmmal.ini和dmwatcher.ini里的实例角色配置,以及归档配置是否与新集群匹配。
4.3 应用恢复与连接验证
很多团队在主备切换验证后,忽略了应用侧的恢复测试,导致演练结束后业务仍处于故障状态。应用侧至少应该验证这几项:
- 连接池是否能在旧连接断开后自动重连到新主库。
- 事务重试机制是否正常,切库瞬间未完成的事务能否安全回滚。
- 核心交易接口在切换前后是否能保持可用。
如果你的环境是通过VIP漂移来实现应用透明访问,那么还要验证VIP是否成功绑定到新主库,并确认ARP缓存刷新情况。数据源、客户端缓存的问题往往在切换后几分钟内集中爆发,这也是为什么演练要预留足够的观察窗口,不要切完马上宣布成功。
5. 常见问题与避坑实录
5.1 故障演练高频问题速查表
我把这些年演练过程中遇到的高频问题整理成了一张表,方便你对照排查:
| 常见现象 | 可能原因 | 排查思路 | 规避建议 |
|---|---|---|---|
| 监视器迟迟不触发自动切换 | 监视器权限配置不足,或心跳检测周期过长 | 检查dmmonitor.ini中的自动切换配置;查看监视器日志 | 演练前确认自动切换开关为打开状态 |
| 切换后新主库无法对外提供服务 | 新主库启动模式仍是Mount,未切换到Open | 登录新主库查看实例状态 | 在切换流程中增加状态校验步骤 |
| 原主库恢复后重复抢占主库角色 | 旧守护配置未清理,启动时误判角色 | 检查dmwatcher.ini及实例初始模式 | 恢复前清理旧配置并修改启动参数 |
| 备库日志追平时间过长 | 归档日志积压过多,网络带宽不足 | 查看日志发送队列,确认MAL配置 | 定期归档清理,提升网络带宽 |
| 切换后部分业务连接报错 | 连接池缓存了旧主库地址,VIP未漂移 | 检查应用日志和网络连接状态 | 配置多地址Failover或VIP,定期演练验证 |
这张表不是标准答案,但方向上值得参考。每个人环境不同,关键是要建立一套自己的“异常现象—原因—动作”对照表,演练后持续完善。
5.2 演练最后别忘了恢复生产配置
演练完成后,整个环境应该恢复到最初状态:新主库如果继续承担主库角色,那么原主库已作为备库重新加入;如果业务要求恢复到演练前的拓扑,那么需要再做一次计划内切换。无论哪种路径,最终要确保集群处于健康状态,并重新检查日志同步和守护进程状态。
最怕的情况是演练结束就下班,留下一个“新主库在跑、旧备库还没追平”的中间状态,这等于主动制造了一个新的故障隐患。我每次演练结束都有一个固定动作:重新打开监视器跑一遍show health命令,打印集群全貌截图存档,确认所有节点都处于期望状态才签演练确认单。
5.3 演练周期与演练报告
DM实时主备故障模拟不是一次性工作,而是需要周期性执行的运维动作。我通常是每季度做一次完整演练,每次演练后输出包含切换时间线、数据校验结果、问题清单和改进建议的演练报告,同时将演练中发现的问题纳入下个月的整改计划。这样循环下来,主备集群的“可信度”会越来越高,下次再被问到“到底能不能切换”的时候,你就有实打实的数据和报告可以回答。
6. 我的个人体会
演练做得越多,越发现主备集群的真正难点不在于“主备怎么切”,而在于“切完之后整个系统能不能无缝继续服务”。数据库层面只是最小的一环,网络、应用、监控、人员权限,每个环节都可能在关键时刻拖后腿。
在实际操作中,我最大的一个感悟是:先把业务方拉进演练复盘会,把数据库层面的切换结果翻译成业务能够理解的语言,比如“RTO可以做到多久”“数据丢失窗口是零还是有几秒”“什么时候可以恢复写入”。只有业务侧真正认可这套机制,主备集群的存在才有意义,否则DBA自己演练再熟练,对组织来说价值都是打折的。
最后再分享一个小技巧:每次演练前,我会临时关闭生产环境一些不必要的自动告警,只保留主备集群相关的核心告警,避免演练期间触发大量误报,典型的告警疲劳反而会让人忽略真正的异常。演练结束后再恢复所有告警规则。这个动作虽然简单,却能让整个演练过程清爽很多,也方便事后复盘时聚焦关键日志。