作为 DBA,最怕听到的一句话就是“把库切一下吧”。“切库”在达梦数据库 DM8 的日常运维里,既可能是一次计划内的主备切换,也可能是一场毫无征兆的故障应急。我最早接触 DM8 切库时也踩了不少坑,总觉得它是高危操作,后来把原理和步骤彻底捋清楚之后才发现,切库本身并不可怕,可怕的是你对集群当前状态一无所知就动手。这篇内容就是把我自己在 DM8 主备环境里做切库的完整经验整理出来,从概念、架构到实际操作和问题排查,尽量做到能直接照着做。
这篇文章适合谁?正准备做信创迁移、需要维护 DM8 主备环境的 DBA,以及第一次接触达梦数据守护的运维同学。如果你连“主库和备库靠什么同步”都不太清楚,建议先看第 2 章;如果环境已经建好、只想知道切换命令怎么敲,可以直接跳到第 3 章和第 4 章,但真出了事故,还是要回来补原理。
1. 先搞清楚:“切库”到底在切什么
1.1 业务侧和 DBA 侧对“切库”的理解不一样
我在实际工作中发现,“切库”这个词在会议室里和工单系统里含义差别很大。业务同事说的“切库”,通常是指把应用系统的数据库连接从原来的实例改到另一个实例上,比如从旧机器迁到新机器、从一个数据库实例切换到另一个数据库实例,他们关心的是“业务什么时候能恢复、数据会不会丢”。而 DBA 说的“切库”,在 DM8 语境下,绝大多数时候指的是主备数据守护环境下,把数据库服务从主库切换(或强制切换)到备库的过程。
这两种理解不冲突,但如果你在搭建或维护 DM8 主备集群,就必须把两边都照顾到。DBA 要做的不只是把数据库角色从 Primary 变成 Standby,还要保证业务连接能跟着切过去,否则你这边切换成功了,业务却还盯着旧 IP 猛连,照样是事故。所以本文说的“DM8 切库”,我把它定义为:在一个由两节点(或多节点)构成的数据守护集群中,将数据库主备角色重新分配,并把业务流量平滑或应急地转移到新主库上的完整过程。
1.2 三种典型切库场景:计划内切换、故障切换、容灾演练
我总结下来,日常会遇到三类切库需求:
第一种是计划内切换(Switchover)。比如主库所在机器要做硬件升级、操作系统补丁、磁盘扩容,或者达梦版本需要小版本升级,这时候你不想让业务长时间停摆,就会提前把主库角色切换到备库,等维护窗口结束再切回来。这种切库要求两个节点都健康,数据完全一致,整个过程可控、可回退,是平时最容易练习的场景。
第二种是故障切换(Failover)。主库宕机、机房断电、存储损坏,备库被提升为新主库,保证业务尽快恢复。这种切换往往是应急操作,特点是“快”和“稳”优先,不一定要求原主库还能用,但一定要尽量避免数据丢失,或者至少要清楚丢失了多少数据。
第三种是容灾演练。很多甲方和监管要求每年做一两次灾备演练,验证 RPO/RTO 是否达标。演练本质上就是故意制造切换场景,检验备份、归档、守护链路和人员操作流程是否可靠。我见过不少平时没演练过、真出故障时手忙脚乱的现场,说实话,没练过就别指望事故时能冷静操作。
1.3 切库前必须想清楚的三个问题
在动手之前,我通常会先问自己三个问题,也建议大家养成这个习惯:
- 这次切库允许多久的业务中断时间?计划内切换可以控制在秒级甚至分钟级,需要提前通知业务方;故障切换则要根据监视器自动/手动模式来预估恢复时间。
- 这次切换允许丢失多少数据?如果备库和主库是同步模式(SYNC),理论上切换不丢数据;如果是异步模式(ASYNC),主库故障时备库可能缺少最近一小段日志,必须对业务方如实交代。
- 切换失败怎么办?有没有回退方案?如果备库转主库失败,原主库是否还能继续服务?很多人只准备“切过去”的方案,不准备“切回来”的方案,这在生产环境是大忌。
把这三个问题想明白,切库就不再是“赌运气”,而是有预案的常规操作。
2. 切库背后的机制:DM8 数据守护是怎么工作的
2.1 主库、备库、守护进程、监视器分别扮演什么角色
要理解切库,先要理解 DM8 数据守护集群里的几个角色。我习惯用“公司双机热备”来打比方:主库是正在接待客户的正式员工,备库是随时准备好顶班的备份员工,守护进程像是盯着员工状态的班长,监视器则是坐在办公室里的主管。
- 主库(Primary):对外提供读写服务,所有业务写入都发生在主库。
- 备库(Standby):持续接收主库产生的 REDO 日志,并应用日志保持数据更新。备库平时不提供业务读写,但可以承担只读查询(部分场景下)。
- 守护进程(dmwatcher):每个节点上都有一个守护进程,负责监控本节点数据库状态、跟对方节点通信、维护集群角色状态。它既看数据库死活,也看网络是否健康。
- 监视器(dmmonitor):可以单独部署在一台机器上,也可以放在某个节点上。监视器负责收集集群状态、展示信息,并下发切换命令。确认监视器(Confirm Monitor)才有权限自动执行故障切换,非确认监视器只能看不能切。
实际配置时,每个节点要启动数据库实例和守护进程,监视器则独立运行。如果监视器部署在某一台数据库节点上,注意别把守护进程和监视器的配置搞混,它们是两个不同的程序。
2.2 日志同步、状态机与切换的三层基础
DM8 主备数据同步靠的是 MAL 系统(达梦的内部通信机制)。主库每产生一条 REDO 日志,就通过 MAL 通道把日志传递给备库;备库收到日志后写入本地日志文件并应用,从而跟主库保持一致。这和很多传统数据库的主备原理类似,理解起来不难。
但切换能不能成功,依赖的是另一层东西——集群状态机。达梦数据守护把实例角色分成 Open(运行)、Mount(装载)、Suspend(挂起)等状态,守护进程实时维护主备机状态。只有当两个节点状态都符合切换条件时,监视器才允许执行 Switchover;如果主库已宕机、心跳中断,则需要走 Failover 流程,强制把备库提升。你可以把状态机理解为“切换都遵循一套严格的交规”,不是想什么时候切就能切,也不是主库挂了备库就一定能自动顶上。
第三层是配置层。DM8 数据守护的关键配置散落在几个文本文件里,比如 dm.ini、dmmal.ini、dmwatcher.ini、dmmonitor.ini。切换时监视器会重新读取这些配置,并向守护进程下发指令。配置文件写错,哪怕只错一个实例名,都可能导致监视器连不上集群,切换自然无从谈起。
2.3 切库依赖哪些核心文件,它们各自管什么
我把核心配置文件的作用整理成一个表,方便你对照检查:
| 文件名 | 作用 | 出了问题会怎样 |
|---|---|---|
| dm.ini | 数据库实例的主要参数,其中有实例名、端口、归档配置等 | 实例启动失败或端口不对,守护进程无法监听 |
| dmmal.ini | 配置 MAL 系统,包括各实例的 MAL 端口、MAL 主机、实例名 | MAL 链路建立失败,日志无法传输 |
| dmwatcher.ini | 守护进程配置,定义守护类型(本地/全局)、守护模式(同步/异步) | 守护进程无法启动或无法正确判断主备状态 |
| dmmonitor.ini | 监视器配置,定义要监控哪些守护进程、是否为确认监视器 | 监视器看不到集群、无法执行切换命令 |
| dmarch.ini | 归档配置,本地归档和远程归档都要配好 | 备库收不到日志,切换后丢数据 |
任何时候做切库,我都强烈建议先把这几个文件备份一份,并核对实例名和 IP,不要相信记忆。切库这活不怕慢,就怕“我以为配置是对的”。
3. 计划内切换(Switchover)完整实操过程
3.1 切库前的环境确认与检查清单
计划内切换前,我会按下面这个检查清单走一遍,确认无误才动手。这不是走形式,而是避免切到一半发现备库根本没同步上,那种骑虎难下的感觉实在难受。
- 确认主备库都处于 Open 状态:通过 disql 连接每个实例,执行查询,确认数据库状态是 OPEN、角色分别是 PRIMARY / STANDBY。
- 确认日志同步状态正常:在监视器里执行 show 命令,查看两个节点的状态,重点看“同步状态”是不是正常。备库应用日志是否跟上主库,直接决定切换后数据完整度。
- 确认归档空间和日志传输正常:检查本地归档目录是否可写、空间是否充足,主库到备库的远程归档是否在持续产生。归档断了,备库就可能跟不上。
- 确认业务侧停机窗口:和业务方达成一致,明确开始时间和结束时间,准备好切换后需要修改的连接串、JDBC 配置、客户端配置。
- 备份配置文件:把 dm.ini、dmmal.ini、dmwatcher.ini、dmmonitor.ini 都拷贝一份,打上时间戳。万一切出问题要回退,这些文件能救命。
- 检查监视器可用性:确认能正常登录监视器,能 show 出两个节点信息。如果监视器连不上集群,那就谈不上切换。
在这个阶段,我常用的查询语句是:
-- 在 disql 中查询实例角色和状态 SELECT INSTANCE_NAME, STATUS, MODE$ FROM V$INSTANCE;正常情况下,主库返回 PRIMARY,备库返回 STANDBY,两边 STATUS 都是 OPEN。如果备库状态是 MOUNT 或者其他异常值,先别切,把同步问题解决再说。
3.2 在监视器中一步步完成 Switchover
确认无问题后,开始执行切换。下面是我在实际项目里反复验证过的一套流程,以监视器命令行操作为例。
第一步,启动监视器。如果监视器部署在独立机器上,进入 DM8 安装目录的 bin 目录,执行:
./dmmonitor /dmdata/dmmonitor.ini启动后进入 dmmonitor 的命令行界面,先登录:
login按照提示输入用户名(一般是 SYSDBA)和密码。
第二步,查看集群整体状态:
show这个命令会列出集群中所有实例的详细信息,包括实例名、角色、状态、守护进程状态、归档情况。我习惯重点看“主库”状态是否为 OPEN,“备库”状态是否 OPEN,还有一个容易被忽略的“监视器连接”状态。如果备库显示连接正常,再继续。
第三步,执行切换命令。达梦监视器中切换主备的命令是switchover,需要指定要把哪个实例切换为新主库。这里有一点要注意:不是输入“备库实例名”就完事,而是确认当前集群中哪个实例是健康备库,把它指定为新主库。典型命令如下:
switchover <备库实例名>比如,当前主库实例名是 DM_A,备库是 DM_B,想把 DM_B 提升为新主库,执行:
switchover DM_B命令执行后,监视器会做一系列自动化动作:先检查集群状态,符合条件则向当前主库下达角色转换指令,主库转为 Standby,备库升级为 Primary。整个过程通常几秒到几十秒,取决于日志量、磁盘性能和网络状态。我在生产环境里实测过,空闲状态下切换大概在 10 秒左右,业务中断窗口主要花在应用层切换连接上。
第四步,再次用show确认结果。看到 DM_A 变成 STANDBY、DM_B 变成 PRIMARY,且两边状态都是 OPEN,说明切换成功。
注意:执行 switchover 之前,确保当前没有未提交的长事务,也没有大量活跃会话压在主库上。如果业务在切换窗口还在持续写入,切换过程会等待日志同步完成,表现为“切换中”时间变长。最好先在应用侧暂停写流量,切换完成并确认后再恢复。
3.3 切换后的业务验证与回切准备
切换完成后,最重要的工作是验证业务,而不是急着收工。我会按这个顺序做验证:
- 用新主库建表、插入数据、查询数据,确认读写功能正常。最简单的测试:
-- 在新主库上执行 CREATE TABLE T_SWITCH_TEST (ID INT); INSERT INTO T_SWITCH_TEST VALUES(1); COMMIT; SELECT * FROM T_SWITCH_TEST;能正常执行并返回,说明新主库对外服务没问题。
检查旧主库是否正常转为备库,并且在持续接收新主库的归档。如果旧主库归档中断,说明回切路径已经断了,越早发现越容易修复。
同步应用连接配置。这一步是切库最容易出问题的环节。如果应用用了双 IP 高可用配置,确认配置指向了新主库 IP;如果用了域名绑定,确认 DNS 或 hosts 已更新;如果用了达梦 JDBC 的连接串,确认 IP 端口对应的是新主库。我遇到过好几次切换本身非常成功,但应用配置没改,结果业务一直报连接失败,最后发现是连接串里的备库 IP 已经变成新备库,读写请求全打到备库上去了。
观察一段时间。切换后至少观察 15 到 30 分钟,查看新主库的会话数、锁等待、慢 SQL,确认没有异常。如果一切正常,再把这次切换的时间、原因、操作人记录到运维文档里。
至于回切,原理和正向切换完全一样。等原主库所在主机维护完成、集群恢复同步后,在监视器里把原主库实例名填到 switchover 命令里,再切回来即可。我建议回切安排在下一次维护窗口,不要刚切完就急着回切,给业务一段稳定观察期。
4. 故障场景下的切库:Failover 与应急兜底
4.1 主库宕机时,先判断是自动切还是手动切
主库宕机时,最忌讳的就是一群人围过来乱敲命令。第一步永远是打开监视器,确认集群到底处于什么状态。如果是确认监视器,且配置了自动故障切换,达梦守护进程会自动把备库提升为新主库;如果自动切换没有发生,再考虑手动 Failover。
我遇到过自动切换失败的情况,常见原因包括:确认监视器没有启动、监视器配置文件里没有把当前监视器设为确认模式、两个节点之间的网络抖动导致守护进程误判但仍然未触发切换。这时候不要慌,手动 Failover 就是兜底方案。
手动 Failover 之前,要尽可能确认主库已经彻底不可用。为什么?因为 Failover 是把备库强制提升为主库,如果原主库其实还能对外提供服务,两个节点就可能出现“双主”脑裂风险。虽然达梦守护有防脑裂机制,但我们要尽量避免这种局面。如果连接主库的网络完全不通、无法登录,或者登录后发现实例已经挂掉、无法拉起,就执行 Failover。
4.2 手动 Failover 的步骤与注意事项
手动 Failover 的操作同样在监视器里完成。
进入监视器并登录后,先执行show观察状态。如果看到主库状态异常、备库还在 OPEN,且守护进程没有自动完成切换,则执行:
failover <备库实例名>指定要把哪个备库提升为新主库。
Failover 与 Switchover 的最大区别在于,Switchover 讲究“平稳交接”,要求主库配合完成角色移交;Failover 则是“单方面宣布”,备库直接接管角色,不再等待主库回应。因此 Failover 执行速度通常更快,但代价是原主库上那部分尚未传到备库的数据会被丢弃。如果原来配置的是 SYNC 同步模式,且主库宕机前所有已提交事务都已被备库接收,那么 Failover 可以做到不丢数据;如果是 ASYNC 模式,丢数据几乎是必然的,只能尽量缩小损失。
执行 Failover 后,同样用show确认新主库状态为 PRIMARY、OPEN。然后立即通知业务方切换连接,并按新主库 IP 更新应用配置。
提示:Failover 是应急手段,不是常规操作。如果不是真实故障,不要为了练手而随便执行。平时演练时,可以用一个测试集群专门模拟故障,避免影响生产。
4.3 故障切换后的善后:原主库修复后怎么加回集群
很多人在故障切换成功后松了一口气,觉得事情结束了。实际上,真正的麻烦才刚开始:原主库修复后,不能直接把它当备库加回去,它的数据已经落后于新主库,甚至可能脑裂过,直接加回去会破坏集群一致性。
我通常的做法是:先把原主库的数据库实例停掉,备份原有的数据文件和控制文件(不要轻易删),然后把它当作一个全新备库重新初始化。如果新主库提供了备份,就用备份来恢复;如果没有合适的备份,需要先在新主库上做一次在线备份或物理备份,再把备份传到原主库节点上,执行还原恢复操作,让它重新追上新主库的日志。
这个过程对初学者来说比较繁琐,但思路是固定的:先备份、再还原、再同步。千万不要图省事,直接把原主库的数据文件覆盖回集群,那会让整个集群处于不可信状态。等原主库重新变为 STANDBY 并和主库同步一致后,再考虑是否把它纳入自动切换范围。
5. 典型切库失败原因与排查经验
5.1 切换卡在“切换中”状态,怎么定位
我印象最深的一次切库故障,是在一次计划内切换时,监视器执行 switchover 后一直显示“切换中”,业务已经停了十来分钟,所有人都盯着屏幕干着急。后来排查下来,原因是主库上有一个长时间运行的查询会话,一直占用着系统资源,日志同步迟迟无法收尾,切换流程只能等待。
遇到“切换中”卡住,我建议按以下顺序排查:
- 在主库(如果还连得上)上查看活动会话,用
SELECT * FROM V$SESSIONS;看看有没有长时间未提交的事务或大型查询。 - 查看守护进程日志和监视器日志。守护进程日志通常记录在配置指定的日志路径里,重点看有没有“wait log”或“timeout”相关字样。
- 确认主备库之间的网络是否正常,MAL 通道是否存在大量重传。
如果确认有长事务阻塞,可以先排除阻塞源,让事务结束,再观察切换是否继续。如果没有长事务但依然卡住,就要考虑是否配置中同步超时时间设置过短,适当调整后再重试。
5.2 监视器连接失败、守护进程报错的常见原因
监视器是切库的“驾驶舱”,一旦连接失败,后面什么都做不了。我梳理了自己遇到过的几类问题:
| 现象 | 可能原因 | 解决思路 |
|---|---|---|
| 监视器启动即报“无法连接” | dmmonitor.ini 中配置的守护进程 IP 或端口错误 | 检查 dmmal.ini 中对应的 MAL 端口,确认守护进程是否正常启动 |
| login 报用户名密码错误 | 达梦初始化时设置的 SYSDBA 口令忘记或变更 | 使用正确的口令,注意大小写;必要时由系统管理员重置 |
| show 只能看到一个节点 | 另一个节点的守护进程未启动,或网络隔离 | 登录对应节点,启动 DmWatcherService 服务,检查状态 |
| 守护进程启动后退出 | dmwatcher.ini 中实例名与 dm.ini 不一致 | 核对两个文件中的实例名、端口、MAL 主机配置 |
我的一个习惯是:刚搭好环境时,先不急着做切库演练,而是反复执行show,直到能稳定看到两个节点、且状态长时间不发生变化。如果 show 的结果都不稳定,说明搭建阶段就有问题,勉强切换只会在事故现场暴露更多隐患。
5.3 切库常见问题速查表
根据我多年踩坑的经验,整理一个速查表,方便你复制到自己的运维手册里:
| 问题 | 快速判断 | 处置建议 |
|---|---|---|
| 切换后应用连不上 | 应用连接的 IP 是否指向旧主库 | 更新 JDBC/连接串配置,或启用负载均衡中的新主库 |
| 切换后数据缺失 | 备库日志应用滞后,或异步模式 | 查明同步模式;对业务方说明数据丢失范围,尝试从归档补回 |
| 回切失败 | 原主库归档中断或状态异常 | 先将原主库重新初始化或恢复为备库,再执行切换 |
| 集群出现双主 | 网络隔离+守护误判 | 立即停掉异常节点的实例,以业务优先连接的新主库为准,重建备库 |
| 监视器无法执行命令 | 确认监视器未配置或权限不足 | 检查 MON_DW_CONFIRM 参数,重新部署确认监视器 |
这张表不是我拍脑袋写的,都是实际运维中反复出现的典型场景。其中“双主”是最危险的,处理原则就一句话:先止血,再复盘。
6. 经验总结:让切库从“高危操作”变成“常规操作”
写在最后,我想分享一点个人体会。我刚接触 DM8 切库时,总觉得切换命令一敲下去,数据库就命悬一线了;后来切换次数多了才发现,真正决定切库成败的,不是最后那几秒钟敲下去的命令,而是切库前那十几个小时甚至几天的准备工作。
我建议大家养成几个习惯:第一,把配置文件和归档日志状态纳入日常巡检,不要只在切库时才想起它们;第二,每个季度至少做一次真正的切换演练,演练时故意模拟网络断开、主库宕机等故障,检验团队的应急能力和监视器配置是否可靠;第三,切库前后的每一步操作都留痕,记录命令输出和截图,万一真出了故障,这些记录会是定位问题的第一手材料。
另外一个非常实用的小技巧:在正式切库前,先把主备两边的表结构、数据量、关键统计信息做一次快照对比。切换后再次对比,如果数据量、行数、关键表的状态都一致,说明这次切换数据层面没有问题;如果不一致,就能立刻定位到同步断点,而不是等业务投诉后才去翻日志。这个方法成本很低,但能给切库增加很大的确定性。
最后再提醒一句:切库不是一个人的操作,一定要让业务方、应用开发、监控值班的人都参与进来,提前约定好通知口令和回滚决策链。数据库切得再漂亮,业务没人配合,最后也是一场空。希望这篇 DM8 切库实战的经验能帮你少走弯路,真正把切换这件事拿捏住。