前段时间刚帮一个客户把跑了两年多的DMHS同步链路平滑升级到了DMDRS,整个过程没停业务,数据零丢失,整体切换窗口控制在分钟级。这次实操我特意记录下来,因为“柔性升级”这四个字听起来很体面,但做的时候坑非常多,稍不留神就从“柔性”变成“折腾”。如果你是正在跑DMHS、又打算往DMDRS迁移的同行,这篇内容应该能帮你少走不少弯路。
先说清楚这次做的事情:把达梦数据库环境里原有的DMHS数据同步任务,在不中断业务的前提下,迁移到新一代的DMDRS复制服务上。DMHS我们跑了很久,稳定是大前提,但新链路带来的DDL支持、断点续传、CDC读取能力和统一管理体验确实更贴近现在的业务需求。所谓“柔性”,核心就是双轨并行、先追平、再切换、留回退,而不是传统那种“停库、卸工具、装新工具、全量重灌”的暴力搬迁。
这次实战涉及的内容比较杂,从环境摸底、数据一致性校验,到DMDRS部署参数、切换回退,再到各种连接工具和驱动报错,我都会按实际操作顺序来讲。前面部分偏思路,中间部分偏手把手操作,后面部分是一堆排障速查,建议按需跳读。
1. 升级的背景、痛点和目标
1.1 DMHS和DMDRS到底有什么区别
DMHS是达梦经典的实时同步工具,很多生产环境都在用,主要做数据库间的数据抽取、传输和写入。它的工作方式偏向于“同步任务”这个概念:你配置一条源端到目标端的同步链路,它帮你持续搬运数据。这个模式在链路少、结构简单时非常稳定,很多老项目一跑就是好几年。
DMDRS是后面推出的数据复制服务,定位更接近一套独立的复制框架。它不是简单的一条同步任务,而是把数据捕获、日志分析、任务调度、目标端应用拆分成了更清晰的模块。从使用体验上说,DMDRS对多链路管理、动态调整、DDL同步、CDC开放读取这些场景友好得多。尤其当你需要同一份数据同时分发到多个目标端,或者目标端需要按表拆分路由,DMDRS的架构优势会非常明显。
1.2 为什么业务稳定还要升级
我知道很多人会有这个疑问:DMHS跑得好好的,为什么要折腾?这次客户的情况比较典型,主要有几个痛点逼着他们下决心:
第一,DMHS旧版本对DDL同步的支持比较弱。开发那边经常要加列、改注释,一次DDL变更就得手动干预同步任务,漏一次就可能导致后续数据错位。
第二,断点续传和位点管理不够灵活。网络抖动或者目标端维护导致链路中断,恢复后找起点比较费劲,严重时只能重灌部分表。
第三,业务在扩展,需要加新的目标端。老架构下每加一个目标端基本等于多维护一套独立任务,管理成本直线上升。
第四,应用侧开始对CDC数据有消费需求。像“达梦数据库获取读取到的CDC”这种场景,DMDRS开放能力比DMHS更直接,能让下游应用拿到变更流。
所以这次升级不是赶时髦,是业务结构变化后的必然选择。但正因为老链路稳定,才不能粗暴替换,必须柔性过渡。
1.3 什么样的情况不适合立刻升级
我也想给一句实在话:不是所有环境都适合这次升级。如果你只是单条DMHS链路、结构固定、几年不变,那真没必要为了升级而升级。任何同步工具迁移都是有风险的,尤其涉及历史遗留配置和定制化脚本时,迁移成本可能比收益还高。
适合升级的信号有三个:一是链路数量在增长,二是DDL和CDC需求变多,三是你经常要手工干预同步任务。如果三个一个都不沾,可以继续稳着跑。这个判断一定放在升级规划之前,别领导一句“要换新的”就埋头开干。
2. 升级前的环境摸底与兼容性排查
柔性升级的第一件事不是装DMDRS,而是把现有环境彻底摸清楚。我见过太多项目跳过这步直接部署,结果切换时发现版本不兼容、驱动不对、权限不够,只能在生产环境里手忙脚乱。
2.1 确认数据库版本、DMHS版本和DMDRS版本
不同版本之间兼容性差异很大,尤其达梦8各小版本之间,DMDRS对数据库版本有明确要求。我这次先做了三件事:
- 查数据库版本:
SELECT * FROM v$version;,确认大版本和小版本补丁号。 - 查DMHS版本:登录DMHS管理端看版本信息,同时记录当前正在跑的同步任务清单。
- 确认DMDRS安装包版本:必须和数据库小版本对得上,否则可能遇到内部接口不兼容,启动都困难。
这里容易踩的坑是:数据库升过补丁,但DMHS还停留在很久以前的版本。新部署的DMDRS要求数据库至少是某个基准版本,低于版本就需要先给数据库打补丁。千万别觉得“能用就行”,到启动DMDRS时各种报错会让你怀疑人生。
2.2 网络、端口、账号权限一次性摸清
同步工具对网络是有硬性要求的,源端和目标端之间的关键端口必须通。我这次操作前做了个清单:
- 源端数据库服务端口、DMDRS服务端口、管理端口。
- 目标端数据库服务端口,以及各节点主机之间的TCP连通性。
- 如果涉及多网卡或者防火墙策略,必须确认同步流量走哪条网卡,避免走了低带宽链路影响追数速度。
账号权限也要提前确认。DMDRS源端账号一般需要读取归档日志或CDC能力的权限,目标端账号需要建表、写入、删改的权限。权限不够时,全量初始化阶段报错还算好排查,最怕增量阶段某些DDL执行到一半失败,处理起来非常恶心。
如果你平时习惯用Navicat连接达梦数据库,这里顺便提醒一句:测试账号的时候,务必用实际生产连接串和驱动版本去连,别用Navicat连通了就以为数据库层面OK。Navicat能连通只能说明TCP和基本认证没问题,同步工具需要的内部权限还差得远。
2.3 驱动、ODBC、JDBC连接串的准备
这部分容易乱,因为我发现很多同行的服务器上有多个版本的达梦驱动,JDBC驱动、ODBC、管理工具各自用一套,版本还不一致。DMDRS部署前最好统一:
- JDBC驱动:下载达梦官方对应版本的JDBC驱动,放到统一目录,记录版本号。应用侧如果是SpringBoot项目,建议直接看Dm8JdbcDriver版本,而不是随便拿个老jar包。
- ODBC配置:如果你的同步链路需要ODBC方式连接目标端,要单独配置
odbc.ini,关键是版本位数要和调用方一致,32位工具链配64位ODBC一定会出问题。 - 连接串写法:达梦JDBC连接串常用格式是
jdbc:dm://IP:5236?schema=xxx,注意schema参数直接影响默认模式,很多“模式错误”问题就是这个参数没写对。
这里多说一句DBeaver。我知道有些同事喜欢把达梦切到PostgreSQL模式用DBeaver连接,确实很多时候比自带工具顺手。但DMDRS部署不影响你用DBeaver还是IDEA连接,工具选择是个人习惯,真正决定链路稳定的是驱动和账号权限,别在这上面花太多时间纠结。
2.4 把现有DMHS架构画成一张图
动手部署前,我建议你一定把现网的DMHS同步架构完整画出来。要画清楚的东西包括:
- 源库到目标库是一对一、一对多还是级联同步。
- 同步对象是整库、指定schema还是几张表。
- 是否有双向同步、是否存在环路。
- 是否有自定义转换规则或冲突处理策略。
这张图就是后面设计DMDRS链路的依据。这次我碰到的情况是源端一套生产库,目标端两个库,一台做实时的报表查询,一台做数据归档。老DMHS用了两条独立任务,迁到DMDRS以后我直接在一个复制服务里建了两条分发链路,管理界面清爽很多,源端日志读取压力也明显下降了。
3. 数据一致性基准是柔性升级的生命线
很多人对“柔性”的理解就是不停机直接切,但真正让升级能安全推进的前提,是你能拿到一个可信的数据一致性基准。没有这个基准,后面所有“追平”“切换”“验证”都是空中楼阁。
3.1 先给目标端做一次全量数据核对
我建议在DMDRS部署之前,先对现有DMHS同步出来的目标端数据做一次整体体检。不用每张表都billion级别全量比对,但关键业务表必须覆盖。
具体做法:
- 取源端和目标端的核心表行数,直接
SELECT COUNT(*)。 - 对数据量大的表,用分组聚合算一个简单的checksum,比如
SUM(CRC32(主键||关键字段)),两边对比。 - 抽几张典型大表做字段级明细抽样比对,确认不是只数量对、内容错。
这次体检发现了一个很有意思的问题:DMHS老任务里有两张表的映射关系配置错了,导致目标端表结构一直少一列,数据虽然同步了很多年,但应用查询时都是按旧结构取数,已经习惯了。这种历史债如果不提前发现,切到DMDRS时按正确结构同步反而会引发应用报错。所以先摸底再做方案,这句话什么时候都不过时。
3.2 确认DMHS当前的健康度和积压情况
升级前一定要看DMHS的实时运行状态,重点看两个指标:
- 同步延迟:如果经常有分钟级甚至小时级延迟,说明链路本身就有问题。
- 错误队列:是否有长期处理不了的错误事务积压。
如果DMHS当前已经处于亚健康状态,我建议先把老链路治理到平稳再谈升级。因为DMDRS追平增量需要一个稳定的参照系,老链路本身在抖动,你很难判断新链路到底是追平了还是被老链路的延迟误导了。老链路稳,新链路追增量才有意义。
3.3 确定柔性升级的基准位点
柔性升级过程中,两条链路会短暂并行。你不需要让两条链路完全同步到同一毫秒,但必须确定一个新的基准位点。
这次我记录的是源端一个可靠的SCN或时间位点,然后在DMDRS里从这个位点开始做增量捕获。这样即使切换前老链路和新链路有几秒钟差异,只要增量位点设置正确,DMDRS最终能补齐这段时间的数据。
基准位点的记录位置也很重要。我一般会单独写一个升级备忘文件,记录:位点值、记录时间、当前源端SCN、当前目标端最大事务时间。这个文件在切换验证时会反复用到,别随手记在小本子上。
4. 柔性升级的核心思路:双轨并行、追平再切
这次实操最关键的部分来了。所谓柔性,说白了就是让DMDRS在老DMHS旁边并行跑起来,等新链路的耗时追平老链路之后,再把流量和同步职责正式交接过去。
4.1 为什么不能直接停老启新
如果同步链路只涉及离线数据仓库,停掉DMHS、跑一次DMDRS全量、再追增量,完全没问题。但这次涉及的是在线业务查询和归档链路,目标库有应用在实时读,直接重灌会导致:
- 目标端数据出现空窗期,报表查询结果不完整。
- 全量初始化期间,应用如果写入目标端,新旧数据会混杂。
- 一旦DMDRS初始化失败,老链路又停了,回退成本极高。
所以最好的方式是让DMDRS先去同步存量数据,然后持续追取增量,在源端业务不知道的情况下悄悄赶上老链路。这个过程就是“双轨并行”。
4.2 DMDRS部署的基础步骤
我这次是在Linux环境上操作的,大致步骤如下:
- 创建DMDRS安装目录,解压安装包。
- 创建运行用户,建议单独建一个服务账号,不要用root跑同步服务。
- 规划数据目录、日志目录、归档暂存目录,权限给全。
- 初始化配置文件,重点配置源端连接信息、目标端连接信息、服务端口。
- 如果是通过systemd或守护进程方式启动,先注册服务再启动,避免手动进程被意外杀掉。
- 检查启动日志,确认服务进程正常拉起。
这里要提醒一下Docker场景。我知道有同事习惯用docker安装达梦8做测试环境,如果你的DMDRS也要在容器里跑,需要注意容器时区和宿主机时区的一致性。达梦数据库对时间敏感,时区不一致会导致归档时间、增量位点对不上,排查起来非常隐蔽。
4.3 全量初始化与增量追平的操作顺序
DMDRS建链路时通常有两种做法:一种是先只做增量,前置条件是你已经有完整的目标端数据;另一种是全量+增量连做,让DMDRS自己完成存量初始化然后平滑进入增量。
柔性升级场景下,我强烈建议用“先停老链路写目标的关联任务、再全量+增量、最后恢复并行”的策略,但这里有个细节:如果你在DMDRS全量初始化期间,老DMHS还在往目标端写数据,那么全量读出来的数据可能夹杂着增量变更,容易造成主键冲突或数据覆盖。
实际操作上我一般这么处理:
- 如果目标端可以接受短暂只读,就在DMDRS全量初始化期间暂停DMHS往该目标端的写入,全量完成后再恢复DMHS,让DMDRS进入增量追平状态。
- 如果目标端完全不能停写,那就要启用DMDRS的全量比对模式,让它先扫数据再处理冲突,交给冲突策略去兜底。
这次我选择了可接受短暂只读的方案,窗口只有十几分钟,业务完全能接受,但换来的是全量初始化阶段的数据干净,后面追增量轻松很多。
4.4 追平判断的实战方法
怎么判断DMDRS已经追平老链路?不能光看界面上的延迟数字,我用的是“双保险”:
- DMDRS管理端查看增量延迟,确认延迟持续下降并稳定在较低水平。
- 在目标端查最近几条源端刚产生的事务记录,比如取订单表的最后更新时间,对比源端同样记录的时间差。
只要两者都正常,基本可以认为DMDRS已经具备切换条件。这时候我会再观察一个完整业务周期,比如高峰期跑完再看一轮延迟,确认高峰时段也能扛住。
5. 核心参数与运行调优
同步工具部署起来容易,调好参数才是真正体现经验的地方。DMDRS的核心参数不少,下面这几个我这次实际调过,效果直接。
5.1 源端捕获:CDC和归档日志的配合
达梦的CDC读取能力是DMDRS在增量阶段最依赖的。如果你有“达梦数据库获取读取到的CDC”这类需求,源端一定要开好相关配置,至少保证:
- 数据库开启归档模式,归档日志路径空间充足。
- DMDRS源端账号能被授权读取CDC/归档相关视图。
- 日志保留时间要覆盖DMDRS可能中断的窗口,比如网络抖动后重新拉取日志不能因为日志被清理而断档。
空间规划这里我给个参考:归档空间至少按“3天增量日志量×1.5倍”来预留。因为DMDRS追数出现异常,可能需要往回拉一段日志,如果归档已经被清理,那就只能走全量重灌的路了。
5.2 目标端应用:冲突策略、DDL同步和Sequence处理
目标端写入环节,最常见的三类问题就是主键冲突、DDL同步失败、Sequence不同步。
主键冲突的兜底策略我建议按业务区分:核心交易表用“报错并暂停”策略,避免静默丢数据;维度表和历史归档表用“忽略或更新”策略,保证链路持续运行。千万别所有表都用一个冲突策略,否则将来定位问题会非常痛苦。
DDL同步要单独规划。DMDRS对常见DDL支持比较友好,但哪些DDL允许自动下发、哪些需要人工审批,一定要先在测试环境摸一遍。我这次就遇到某张表加字段时带了默认值,目标端执行顺序和源端不一致导致报错,后来靠预先写好的DDL前置脚本解决的。
Sequence问题算是达梦数据库里比较常见的。老DMHS链路切换后,目标端如果继续用旧Sequence,可能和新同步过来的ID撞车。我这次的处理是在切换脚本里加入“达梦删除sequence并重建,按当前表最大ID重置起始值”的操作。这个操作必须按固定顺序来:先停老链路、再查最大ID、重建sequence、最后恢复新链路写入。
5.3 性能调优:批量大小、并行度和刷盘策略
同步性能不完全是堆线程就能解决的。我这次调优主要动了几个参数:
- 批量抓取大小:调大以后源端抓取日志效率提升明显,但会略微增加内存占用,要观察是否触发GC。
- 目标端并行写线程数:并非越大越好,调大后曾出现目标端锁竞争加剧,反而延迟升高,最后控制在和源端表分区数量匹配的水平才稳定。
- 刷盘策略:同步服务自身日志和缓存数据的刷盘频率,测试环境可以追求性能,生产环境建议保留较稳的刷盘设置,避免宕机丢位点。
调优过程中我习惯每改一个参数就观察至少30分钟,记录延迟曲线。同时用“达梦数据库常用命令”去查当前会话、锁等待和索引状态,判断瓶颈到底在源端、网络还是目标端写库。
6. 切换、验证与回退三板斧
双轨并行一段时间后,终于到了切换日。这个阶段我的原则是:切换要有脚本,验证要有清单,回退要有预案。
6.1 切换前的最后检查清单
切换前两小时我会过一遍下面这张清单,任何一项不通过都推后切换:
- DMDRS增量延迟小于阈值,并且稳定超过一个业务高峰周期。
- 目标端核心表行数和源端一致,抽查校验通过。
- 关键Sequence已重建到正确起始值。
- DMHS任务处于可暂停状态,且能快速恢复。
- 所有相关账号连接串、应用配置已提前准备好,处于待替换状态。
- 备份已完成,包括目标端关键数据和DMDRS配置。
这张清单看起来繁琐,但能极大减少切换当天的偶发问题。
6.2 平滑切换的标准操作步骤
这次切换我用的步骤是:
- 暂停DMHS任务,停止老链路继续向目标端写入。
- 等待DMDRS把暂停期间产生的增量全部追平,确认延迟归零。
- 在目标端做一次快速数据校验,确认无差异。
- 切换应用配置:应用连接串、消费端配置从老链路切换到新链路。
- 观察增量延迟和错误日志,持续确认没有复制异常。
- 确认稳定后,正式停用DMHS任务,但不删除配置,保留回退能力。
这里有个很容易忽略的点:切换的不只是数据同步,还有下游应用对目标端库的写入路径。如果应用还在往老链路目标端写数据,而DMDRS也在写同一张表,就可能出现双写覆盖。所以切换前务必梳理清楚哪个应用在写、哪个应用在读,先切写路径再切读路径。
6.3 回退方案:窗口和边界提前定好
柔性升级必须有回退预案,但回退不是无限期的。我这次和业务约定的回退窗口是切换后48小时。窗口内如果出现严重数据问题,按以下顺序回退:
- 暂停DMDRS链路。
- 恢复DMHS任务,重新接管同步。
- 回滚应用连接配置。
- 校验数据一致性,确认老链路正常。
回退窗口过了以后,要安排一次正式的“老链路下线”,把DMHS进程、配置、归档占位全部清理干净,防止两套同步服务同时运行造成管理混乱。
6.4 一个容易被忽略的验证细节
很多人验证同步就是看行数和最大ID,但真正容易出现问题的往往是“数据内容对不上但行数一样”。我建议切换后一定要做几组明细数据比对,尤其是包含金额、数量这类数值字段的表。
我这次就遇到一张订单明细表,行数两边一致,但金额字段部分记录差了几分钱。原因是老DMHS时代有一次任务重跑产生了重复事务,手工修复时只调整了行数,内容残留了旧值。切换后DMDRS从源端重新捕获,反而把这些历史脏数据洗了一遍。如果没有明细比对,这种问题要等业务核账才会暴露。
7. 常见问题与排障实录速查
最后这部分是本次升级过程中遇到或排查过的高频问题,整理成速查,希望能帮你快速定位。
7.1 Navicat、DBeaver和IDEA连接达梦的报错排查
很多同事连达梦习惯用Navicat,最常见报错就是[HY000] 用户名或密码错误 (-2501)。这个报错并不一定是密码真错,可能原因有:
- 密码里有特殊字符,连接串没有正确转义。
- 账号默认模式不是业务schema,导致连接后找不到对象,误以为认证失败。
- 密码大小写敏感,达梦默认对密码的处理逻辑和MySQL不一样。
- 账号被锁定或密码过期,需要DBA确认账号状态。
排查时我会先用达梦自带工具(比如disql)用同一账号连接,能连上就说明数据库侧没问题,问题在驱动、连接串或工具配置。如果自带工具也报错,再查账号状态和密码策略。
DBeaver连接达梦时,有些同事会把连接类型切到PostgreSQL模式,这在某些版本下确实能解析出更多元数据,但“达梦数据库 模式错误”通常不是连接类型的问题,而是默认schema没配对。建议在连接配置里显式指定schema,而不是依赖工具自动识别。
IDEA里连接达梦的坑和DBeaver类似,重点确认驱动版本要和数据库版本一致,尤其数据库打了补丁后,JDBC驱动不升级会出现各种莫名报错。
7.2 SpringBoot整合达梦的典型错误
“mybatis+druid+springboot+达梦数据库”是现在非常常见的组合,升级链路后应用侧偶尔会冒出连接问题。常见的坑有:
- Druid连接池的驱动类名配置错误。
- 达梦数据库的schema名和用户名混淆,MyBatis XML里写了带schema前缀的SQL,切换账号后找不到表。
- 分页方言没配置成达梦方言,导致SQL生成错误。
排查这类问题我建议先抓一次应用完整报错堆栈,别被“连接失败”这种表面信息带偏。大多数情况不是数据库出了问题,而是应用配置没有跟着同步账号切换。
7.3 关于MySQL迁移达梦和Oracle移植的常见误区
这次升级顺便也处理了一些从MySQL往达梦迁移的老话题。我的建议是:不要指望SQL完全不变。达梦对SQL语法有兼容模式,但“兼容模式”不等于“无脑照搬”。
从MySQL移植到达梦,重点检查这几类点:
- 自增列定义方式。
- 字符串类型和默认值处理。
- 日期函数和隐式转换。
- 分页查询写法。
- 特殊字符转义规则。
如果迁移后应用时不时报错,优先怀疑这几个点,而不是怀疑达梦本身。另外,做“达梦全表数据复制”时别用一条INSERT INTO ... SELECT * FROM跑到底,大表会锁定资源,建议分批处理。
7.4 Docker部署和异步备库场景的注意事项
用docker安装达梦8做开发测试环境很方便,但要注意初始化参数。我遇到过容器重启后数据库实例无法自动拉起的案例,原因是没有正确设置容器的初始化命令或内存限制。如果你打算在容器里同时跑测试数据库和DMDRS节点,建议给足磁盘空间,尤其归档日志目录,不然测试跑两天磁盘满了,DMDRS增量会直接卡死。
另外有同事问“达梦8异步备库搭建”和“同步工具升级”哪个更优先。我的理解是两者解决的问题不一样:异步备库解决的是数据库实例级别的高可用容灾,同步工具解决的是数据复制和分发。如果你的生产环境已经做了异步备库,那这次升级DMHS到DMDRS不冲突,反而可以更放心,因为至少数据库实例层面有一层保护。
7.5 升级后建议建立的日常监控指标
切换完成不是终点。我建议在DMDRS运行稳定一周后补充以下监控:
- 增量延迟趋势:核心指标,建议按分钟采集。
- 错误事务数和错误队列深度:一旦出现持续增长要立刻处理。
- 源端归档日志空间使用率:避免日志满导致数据库出问题。
- 目标端写入压力:关注锁等待和慢SQL,判断是否需要调整并行写参数。
- DMDRS进程内存和句柄数:长期运行下是否有泄漏趋势。
监控数据不用搞得多花哨,能让你在故障发生前看到异常信号就够了。
最后说一点个人体会。柔性升级这件事,最考验人的不是DMDRS配得对不对,而是你对现有系统的理解够不够深。这次能做到业务不停、数据不丢,很大程度上靠的是切换前把老链路的每一个细节都摸了一遍,包括那些“运行了很久但谁也没注意”的映射错误和脏数据。如果你正在准备类似升级,建议把时间多花在前期的环境摸底和数据校验上,这一步做得越扎实,切换当天就越从容。还有个实用建议是:升级当天一定要让业务核心负责人全程在场,因为数据对不对,最终只有业务能给你最权威的答案。