达梦数据库集群在线剔除异步备库实验
如果你维护过达梦数据库的数据守护集群,应该对“异步备库”这种角色不陌生。它平时安静地挂在集群里,负责容灾归档或离线查询,存在感不算高;可一旦某台备库所在硬件需要升级、机房链路要调整,或者节点要腾出来做其他用途,麻烦事就来了:怎么在集群运行着、主库业务不能中断的情况下,把一台异步备库干净利落地摘出去?我最近在一个三节点的达梦数据库演示环境里,完整走了一遍“集群在线剔除异步备库”的流程,中间踩了几个坑,也把相关原理重新捋了一遍。这篇就把实验思路、可执行步骤和排障记录整理出来,给正在做达梦集群维护的人一个直接能抄的操作框架。
1. 这个实验到底在解决什么
1.1 异步备库的角色并不只是“多一个副本”
达梦数据守护集群中,备库大体分为实时备库和异步备库。实时备库追求主备数据基本同步,主库产生的重做日志会尽快传到备库并应用,故障切换时数据损失窗口很小。异步备库则不同,它允许主库和备库之间存在一定的时间差或日志量差,主库通常按归档周期或批次把日志传过去,备库再慢慢回放。这种设计带来的好处是网络压力小、跨机房部署灵活;代价是如果主库突然故障,异步备库在切换后很可能丢一部分最近的数据。
所以生产环境中异步备库的定位一般很明确:要么承担异地容灾的“兜底”角色,要么作为数据分析、报表查询、备份导出的数据源,而不是默认的快速接管节点。明白了这层定位,就能理解为什么会有“在线剔除”这种操作需求。它不是随便删一台节点那么简单,背后涉及同步链路、守护进程、监控器配置、OGUID 标识等一系列状态变更。
1.2 “在线剔除”和直接停备库是两码事
我在不少维护群里看到有人问:备库不用了,直接把实例停掉不就行了?单机环境确实可以这么任性,但集群环境不行。达梦的数据守护集群中,每一台节点都被守护进程和监视器纳管,形成了统一的分布式状态机。如果只是把异步备库的数据库实例关掉,而没有对集群做任何“告知”,后续可能出现三类问题:
- 守护进程会认为该节点发生了故障,反复尝试连接或拉起实例,监控大屏上出现红色告警;
- 主库到该备库之间的日志发送链路还在,长时间无法送达时,归档队列、本地归档空间可能被异常占用;
- AUTO 模式下,集群状态机可能因为节点失联而触发切换评估,本来只想安静撤掉一台备库,结果把主备角色都搅动了。
“在线剔除”的核心,是让集群主动把目标节点从守护拓扑和同步链路中摘除,再让被剔除节点安全退化为独立库或重新初始化。整个过程应该做到主库业务不中断、其他备库同步不受影响、监控视图恢复干净。
1.3 这份实验记录适合谁看
如果你是达梦数据库的一线运维人员,正在规划集群缩容、备库替换或硬件迁移,这篇文章可以直接拿来当操作前检查单。如果你是刚接触达梦数据守护的 DBA,文章里的角色解释、配置项梳理和故障排查思路也能帮你建立对集群拓扑的整体认知。我尽量把思考过程也写出来,不光是列出“点哪里点哪里”,更希望能讲清楚每一步为什么这么做。
需要模型API调用? 免费领10W Token,多模型网关一键接入 Claude、DeepSeek 等主流模型。
2. 先看懂集群的“组织架构”,操作才不会跑偏
2.1 主库、备库、守护进程、监视器各管什么
达梦数据守护集群里有几个很容易混的角色。数据库实例负责提供数据库服务,真正存数据;守护进程 dmwatcher 跑在每台节点旁边,负责监控本机数据库实例状态,并和同组的守护进程交换心跳信息;监视器 dmmonitor 是全局的管理入口,能看到所有节点状态,也可以下发切换、启停等控制指令,其中具有确认权限的监视器才能做真正的故障接管决策。
可以把守护进程理解成每台服务器的“哨兵”,监视器是“指挥中心”。主库对外提供服务,备库从主库拿重做日志进行恢复。异步备库和实时备库在数据守护环境中的差别,主要体现在日志的传输时机和回放模式上。在线剔除一台异步备库,表面上是停掉一个数据库实例,实际上要协调的是“哨兵”和“指挥中心”之间的配置认知。
2.2 同步链路在配置文件里怎么体现
达梦数据守护相关的配置项不少,其中和本次实验关系最紧密的是下面几个:
- dm.ini:数据库实例参数文件,里面和集群相关的重点是 MAL_INI、ARCH_INI、实例名等。
- dmmal.ini:MAL 系统配置,定义了各节点之间的通信地址和端口,相当于集群节点间的“通讯录”。
- dmarch.ini:归档配置,定义了本地日志归档,以及主库向哪些备库发送日志、用什么方式发送。
- dmwatcher.ini:守护进程配置,包含组名、守护模式、OGUID 等信息。
- dmmonitor.ini:监视器配置,声明监视哪些守护进程,以及当前监视器是否为确认监视器。
就拿实时备库和异步备库的区别来说,主库的 dmarch.ini 里可以配置不同归档目标,实时备库对应 REALTIME 类型的日志发送链路,异步备库则可能配置为 ASYNC 类型的异步发送链路。这样主库产生的日志会按不同策略分发到不同备库。理解了这层关系,再去看“剔除异步备库”要动哪些配置,思路就清晰了。
2.3 剔除操作真正要改的是“EP 拓扑认知”
我最初做实验时有个误区,以为在目标备库上把守护进程停掉,再从监视器里把节点删掉就算完事。后来发现,集群里的每个可管理节点在监控体系中是一个 EP(Environment Pointer),EP 信息会出现在各节点的 MAL 配置、守护进程配置、监视器配置里。你单独在一台机器上“退群”,其他机器并不会自动知道这个成员已经不可用。
所以在我的实验环境中,“在线剔除”被我定义为一次有顺序的拓扑状态变更:先让目标 EP 离开集群运行,再在保留节点上清理目标和该 EP 相关的同步链路,最后更新监视器配置,让集群重新达到干净、可监控的状态。整个过程重启动的是守护进程或监视器,而不是主库数据库实例,这就是“在线”的落地方式。
3. 实验环境与操作前的检查项
3.1 三节点数据守护环境拓扑
本次实验搭建的是一个三节点数据守护组,节点 A 是主库,节点 B 是实时备库,节点 C 是需要被剔除的异步备库。三台机器均安装达梦 V8 数据库,使用 dmdba 用户运行。为了便于描述,端口和目录做了简化处理,但整体结构和生产环境保持一致。
| 节点 | 角色 | 用途 | 状态 |
|---|---|---|---|
| 节点A | Primary | 对外提供主库读写服务 | 保留 |
| 节点B | Realtime Standby | 实时同步,保留作为故障切换目标 | 保留 |
| 节点C | Async Standby | 异步同步,承担离线容灾和备份,需要从集群中摘除 | 剔除 |
实验目标不是把节点C关机重启,而是让它彻底退出数据守护组,并且在节点C本地保留一份可以继续使用的数据文件,后续可以独立启动。这样即使以后不重新入集群,这台机器上的数据也仍然可用。
3.2 关键配置模板
在初始化数据守护环境时,我用到的配置主要有三类。先看 dmmal.ini,这个文件决定了各节点通信地址互相是否可达。演示环境里三个节点的 MAL 配置大体如下,重点是每台节点都必须有对端节点的条目:
ini复制MAL_CHECK_INTERVAL = 5
MAL_CONN_FAIL_INTERVAL = 5
[MAL_INST1]
MAL_INST_NAME = GRP1_A
MAL_HOST = 192.168.10.11
MAL_PORT = 5336
MAL_INST_HOST = 192.168.10.11
MAL_INST_PORT = 5236
[MAL_INST2]
MAL_INST_NAME = GRP1_B
MAL_HOST = 192.168.10.12
MAL_PORT = 5336
MAL_INST_HOST = 192.168.10.12
MAL_INST_PORT = 5236
[MAL_INST3]
MAL_INST_NAME = GRP1_C
MAL_HOST = 192.168.10.13
MAL_PORT = 5336
MAL_INST_HOST = 192.168.10.13
MAL_INST_PORT = 5236
守护进程配置文件 dmwatcher.ini 在各节点上结构相同,组名、OGUID 和数据库实例名需要一致。OGUID 是达梦数据守护用来区分不同守护组的重要标识,如果各节点 OGUID 不一致,守护进程会认为彼此不属于同一个组,后面一切操作都无从谈起。
监视器配置 dmmonitor.ini 中比较关键的一项是 MON_DW_CONFIRM,值为 1 表示当前监视器有确认权限。在在线剔除操作中,我希望所有决策都由我手动控制,而不是让自动切换介入,所以实验初始环境中会把监视器配置成确认监视器。
3.3 剔除前必须确认的状态
开始操作之前,我列了一个检查项清单。生产现场很多时候出问题,不是步骤写错了,而是操作前少看了一个状态。
- 当前主库实例处于 OPEN 状态,业务连接正常;
- 实时备库和异步备库状态在监视器中显示为 OPEN 或 MOUNT,且没有中断告警;
- 主库到实时备库的实时归档链路正常,主库本地归档可以正常切换;
- 异步备库最近一段时间没有大量延迟积压,即使有延迟,也已经确认是可接受的窗口;
- 被剔除备库上没有唯一保存在本机、没有其他副本的业务数据;
- 已经通过备份或数据导出方式保留了需要留下的逻辑数据;
- 明确了本次是临时剔除还是永久剔除,因为这两种场景后续清理配置的深度不一样。
这七项里,最容易被忽略的是第一项和最后一项。操作窗口再小,也要先确认主库本身没问题;而“临时剔除”和“永久剔除”的区别,直接决定了主库端要不要删除异步链路条目。如果只是硬件维护两三小时再回来,保留链路可以避免重新配置的麻烦;如果节点彻底退役,残留链路反而会让监控器一直报错。实验中我按“永久剔除”来操作,最后保留节点上的配置会被清理干净。
4. 在线剔除异步备库的完整实施步骤
4.1 第一步:固定集群基线状态
我先启动监视器并连接集群,把当前状态完整看了一遍。这一步的结果要落成文字记录,尤其要记录主库当前的日志序列位置、实时备库的最新回放位置、异步备库的延迟大��。后面的验证阶段,需要对比这些基线值来判断剔除过程是否影响了主库和实时备库。
看状态时我会关注三个层面:数据库实例层面是 OPEN、MOUNT 还是 SUSPEND;守护进程层面是否和本机数据库实例正常配对;监视器层面能否正常收集到所有节点的信息。任何异常,比如某个节点通信超时、监控器状态刷新延迟,都先解决再动手,不带着隐患做拓扑变更。
随后我把守护模式临时切换为 MANUAL,也就是手动模式。这一步非常重要。AUTO 模式下节点之间的异常抖动可能触发自动切换,而我接下来的操作本来就会导致目标节点离线和通信中断,如果不先改成手动模式,实验很容易变成一次“意外故障演练”。切换动作需要在确认监视器会话中完成,不同小版本的达梦监视器命令略有差异,执行前可以用 help 或 show 确认当前版本支持的命令。
注意:把守护模式切到 MANUAL 只影响集群自动故障切换逻辑,并不会关闭数据库实例,所以主库业务连接不会断。
4.2 第二步:让目标异步备库安全离开守护
目标节点 C 要退出集群,顺序很关键。我第一次实验时就因为顺序搞反,差点被守护进程“抢跑”拉起实例。正确顺序是:先停节点 C 上的守护进程,再停节点 C 的数据库实例。
为什么必须这样?守护进程的职责之一就是看护本机数据库实例,如果数据库实例先异常退出,守护进程会按照 INST_AUTO_RESTART 参数决定是否重新拉起它。你停完库还没来得及做下一步,守护进程可能已经又把数据库拉起来了。而先停守护进程,等于先把本机的“哨兵”撤了,之后数据库实例的启停就完全由你手动控制。
操作演示如下:
bash复制# 在节点 C 上执行,先停守护进程
systemctl stop DmWatcherServiceDMSERVER
# 确认守护进程已经退出后,再连接数据库实例执行正常关闭
systemctl stop DmServiceDMSERVER
停止实例之后,我回到监视器里刷新状态。正常情况下,监视器会在超时时间后把节点 C 标记为“通信中断”或“不可达”,但这个异常只是我主动操作产生的,不影响其他两个节点。手动模式下,主库 A 与实时备库 B 仍然保持正常心跳,不会触发切换。
到这里,节点 C 已经和集群“物理上断开”,但拓扑层面还没有清理。如果直接把这个状态当成完成,后续监控会一直刷告警,所以下面继续处理配置残留。
4.3 第三步:在保留节点上清理链路和监控配置
这一步是“永久剔除”和“临时剔除”的分水岭。保留节点 A 和 B 上还需要处理三类配置:
第一类是 dmmal.ini 中的节点 C 条目。只要保留节点上的 MAL 通讯录里还有 C,守护进程就会认为它仍是组成员,日志发送模块也仍会尝试建立连接。
第二类是主库 dmarch.ini 中指向节点 C 的异步归档条目。哪怕目标节点已经不在线,只要这个条目存在,主库在归档日志触发时都会尝试向 C 发送,可能造成不必要的等待或重试。
第三类是监视器配置 dmmonitor.ini 中的节点 C 地址。监视器配置不清掉,它就会一直尝试轮询那个已经退出守护的节点。
我的处理方式是先修改 A 和 B 节点上的 dmmal.ini,把节点 C 对应的三个缩略块注释或删除。同时删除主库 dmarch.ini 中指向 C 的异步归档配置。然后把 dmmonitor.ini 中的对应 MON_DW_IP 地址也移除。
配置改完后,需要重启 A、B 节点上的守护进程,让新配置生效。这一点容易引起误解:重启守护进程不等于重启数据库,主库实例全程不中断,所以业务不会断。但如果你的环境里主库同时承载核心交易,建议选择业务低峰期做,并在重启守护之前再次确认主库 HEALTHY,并且有完整切换预案。
ini复制# dmmonitor.ini 中,剔除前看得到三行;剔除后移除节点 C 对应行
# MON_DW_IP = 192.168.10.13:5236
重启守护进程后,延迟几秒钟再启动监视器,让各个守护进程重新完成组内互联。这时监视器里应该只剩 A 和 B 两个节点,且主库角色为 Primary、实时备库角色为 Standby,整体状态不再是“有节点异常”的黄色告警,而是干净的绿色运行状态。
4.4 第四步:被剔除备库转为独立库
节点 C 未来不再作为数据守护备库,但它还有一套完整的数据文件,我不想直接格式化。为了让它可以独立启动,我把节点 C 的 dm.ini 中与守护相关的参数做了调整,重点是关闭 MAL 相关配置并清掉原来的守护标识。
独立启动之前,还要检查节点 C 上是否存在归档日志发送残留任务,这些任务之前是配合主库链路工作的,现在已经没有对端了。如果启动过程中报归档线程错误,可以在独立模式下调整归档配置,仅保留本地归档即可。这样节点 C 就变成了一台普通的达梦单机数据库,数据文件仍然保留,可以继续承担离线查询或者备份恢复工作。
需要注意,如果你后续想让节点 C 重新加回数据守护组,千万不要在这种情况下直接启动它的守护进程。因为它的控制文件和数据字典里已经带着旧集群的信息,直接接入大概率会出现 OGUID 不匹配或者日志断层的问题。重新入组的正确做法是先从当前主库做一次新的物理备份,再把备份恢复到节点 C,重新配置并初始化守护关系。
4.5 第五步:把剩余集群切回 AUTO 模式并验证
节点 C 已经退出,A、B 两个节点上的配置也已经清理,监控视图不再报错。这时候再把守护模式从 MANUAL 切回 AUTO,恢复自动故障切换能力。
我没有立刻把模式切回 AUTO,而是先观察了十分钟。观察内容包括:
- A 节点的本地归档是否还在正常切换,归档空间有没有异常增长;
- B 节点是否持续从 A 节点接收并应用重做日志,延迟保持在约等于零;
- 监视器日志中不再出现节点 C 的连接失败或超时信息;
- 主库业务会话全程没有中断,相关告警数量为零。
确认这些指标正常后,再进行模式切换。切回 AUTO 的瞬间我会再盯一次监视器,确认两个节点之间状态稳定。最后,我在实验环境的业务侧做了几笔写操作,又停掉主库所在网络模拟了一次短暂故障,验证实时备库能否按预期接管。由于节点 C 已经退出,接管过程只涉及 A 和 B,逻辑清晰很多。
5. 在线剔除过程中的现场问题与排查记录
5.1 现象一:剔除后主库端归档日志不断堆积
第一次实验我没有删主库 dmarch.ini 中指向 C 的异步归档条目,只做了停库和移除监控,当时以为只要 C 不在线,主库就不会再往那个链路发日志。结果不到一个小时,主库的本地归档目录快速增长,日志中还出现了异步发送失败的重试信息。
原因并不复杂,达梦主库的归档发送是配置驱动的。只要异步归档目标还存在,主库在产生归档日志后就会尝试向该目标发送,对端不可达时,相关任务会进入重试状态,而不是自动放弃。这个设计保证了网络闪断后备库还能自愈,但也会让“永久剔除”场景下的主库背上无意义的负载。
处理方式很直接:把节点 C 对应的异步归档目标从 dmarch.ini 中删除,重启守护进程使配置重新加载。之后归档目录恢复平稳。这也提醒我,任何拓扑变更
