☰
达梦数据库从DM7升级到DM8全流程实战与踩坑记录
2026/10/2 18:34:08 网站建设 项目流程

说来有点不好意思,接手公司达梦数据库版本升级这个任务的时候,我对达梦的全部认知基本停留在“听说过、没见过”。在那之前我主要搞的是MySQL和Oracle那一套,对于国产数据库的升级更是从来没实操过。等到真正动手,才发现这根本不是“下载个新安装包覆盖一下”那么简单:光是在升级路径选型上我就纠结了很久,中间还出现过备份集认不出来、导入中文乱码、存储过程编译直接报错这种让人脑壳疼的问题。前前后后折腾了两三天,才算是把测试环境的库平稳切过去。这篇东西就是我当时完整的学习过程和踩坑记录,适合刚接触达梦数据库、或者正准备做达梦版本升级的运维和开发同学拿来当一份避坑参考。

1. 先搞清楚达梦的版本家底,才不会选错升级目标

1.1 达梦不是只有一种版本,先认认门牌号

达梦数据库这些年迭代下来,市面上能见到的主要就是DM6、DM7和DM8这几代。DM6算是老古董了,现在正经生产环境里已经很难见到;DM7是前些年的主力版本,有不少存量系统还在跑;DM8是当前的主推版本,无论性能、安全性还是兼容性都比前代有明显提升。

我这次要升级的就是一套跑在DM7上的业务系统。说实话,DM7在功能上并不弱,它继承了Oracle那一套的编程习惯,存储过程、触发器、物化视图这些东西都用得很顺手。但问题在于,DM7对新的SQL标准支持比较有限,而且随着甲方对安全性和性能的要求越来越高,底层版本的缺陷修复也得跟着新版走,所以升级到DM8是迟早的事。

这里想提醒一个更容易被忽略的点:DM8内部也分了不少小版本。不是说安装了DM8就一劳永逸了,在后续使用过程中官方会发布补丁版本。如果你手里的DM8版本很老,应用里用了某些新特性,或者遇到了一些已修复的Bug,可能还需要在DM8这个大版本内再往上打补丁。所以做“版本升级”这件事之前,第一步是搞清楚当前版本和目的版本分别是什么,别把所有升级都当成“从DM7到DM8”这一个跨度。

1.2 升级的目标版本,不是越新越好

很多刚接触达梦的朋友会有一个惯性思维:升级嘛,肯定要升到最新版。但我这次实际对比下来,发现版本选择的逻辑应该是**“匹配你的应用,而不是匹配你的好奇心”**。

举个例子,如果你的应用还在用比较老的JDBC驱动,或者中间件版本本身不高,那升到最新的DM8小版本未必是最优解。因为你不仅要考虑数据库本身的兼容性,还要考虑下游驱动、连接池、ORM框架这些环节。我那会儿就差点踩了坑:公司的Java应用还在用比较老的DmJdbcDriver,后来升级到新版DM8之后连接直接报协议不匹配,最后是把驱动jar包一起升上去才解决。

所以我的建议是:升级前先列一个清单,把数据库版本、JDBC驱动版本、连接池版本、ORM框架版本这些全部登记一遍,再统一评估目标版本。别光看数据库侧的热闹,应用侧的配套版本跟不上,升级完之后照样跑不了。

2. 升级前的准备工作:不把家底摸清楚,后面全白干

2.1 一条SQL先确认当前版本

在做任何备份和迁移操作之前,第一步永远是确认当前数据库到底是什么版本。这个操作在达梦上非常简单,用disql或者图形化管理工具跑一条SQL就行:

SELECT * FROM v$version;

查询结果会直接显示类似“DM Database Server x64 V7”或者“DM Database Server x64 V8”这样的版本标识。如果你还想看实例级别的基本信息,比如实例名、端口号、启动时间这些,可以接着查:

SELECT * FROM v$instance;

我习惯把这两个查询结果都记录到升级文档里,因为后续无论是写备份脚本还是做恢复,都需要用到实例名和数据文件路径这些基础信息。另外,也可以通过达梦自带的“DM管理工具”在界面左下方的数据库属性里看版本信息,适合不习惯命令行的同学。

2.2 备份是升级的唯一兜底方案

这句话我想放在最前面说:在达梦版本升级这种操作上,备份永远是你最后的安全网。我在这次升级前做的第一件事,就是触发一次完整的物理备份,而不是只导出一两个业务表。

当时我的备份思路是这样的:

  • 用达梦自带的备份管理工具先做一次全库备份;
  • 再用逻辑导出工具dexp把核心业务模式单独导了一份,防止物理备份万一读取失败的时候,还能拿逻辑备份“手动重建表”。

可能有人会觉得做两份备份有点浪费时间,但我的真实感受是:升级这种操作一旦出现意外,返工成本远高于备份成本。尤其是跨大版本升级的情况下,物理备份集的一致性、逻辑导出文件的完整性,都有可能成为最后的救命稻草。

这里顺带提一下,备份文件一定要放到数据库服务器本地磁盘之外的位置,最理想是拷贝到另一台机器或者对象存储上。我当时就把备份文件放到了本机临时目录里,结果后面安装新版本时一不小心初始化了新实例,差点把临时目录覆盖掉,想起来有点后怕。

2.3 兼容性评估要覆盖四个维度,别只盯着表结构

升级前除了备份,还要做一轮兼容性摸底。不要以为数据能导进去就算完事,还要考虑里面的对象、语法和参数在新的数据库版本里是否仍然有效。我这次重点检查了四个方面:

第一个维度是表结构。看旧库中有没有用到新版本已经废弃或者改名了的数据类型。比如某些字符集相关类型、特殊的大对象类型,在新老版本之间的处理逻辑会有差异。最稳妥的办法是把所有表的DDL导出来,挨个扫一遍不常用类型。

第二个维度是存储过程、函数和触发器。这是最容易被坑的地方。达梦的PL/SQL语法整体上兼容Oracle,但DM7和DM8之间在某些内置包、系统函数名称上可能有细微变化。我后面遇到存储过程编译报错,问题就出在这里。

第三个维度是初始化参数。旧实例的dm.ini里配置的参数,有些在新版本中可能已经不生效,或者默认值变了。如果你升级完发现系统性能变化很大,先回来看参数文件。

第四个维度是字符集。这个是最容易引发“升级完中文全是乱码”的元凶。升级前务必确认旧库是什么字符集,新库初始化时也选一样的。我后面会专门展开说这个坑。

3. 三种升级路径,我对比后的取舍逻辑

3.1 图形化DTS迁移工具:上手最快但限制不少

达梦自带一个数据迁移工具DTS,支持从Oracle、MySQL、SQL Server以及达梦旧版本往达梦新版本迁。这个工具的优点是界面化操作,勾选源库和目标库的表、视图、存储过程就可以直接迁移,对命令行不熟的同学比较友好。

我在测试环境里先用DTS跑了一遍全库迁移,发现在十万行级别的小表上速度不错,迁移过程也很直观。但它的缺点是对于超大库、分区表特别多、或者存储过程和序列特别复杂的场景,一旦中途报错,很难从断点继续,往往只能修完重来。而且DTS在批量迁移大数据量表时,效率和带宽利用一般,纯跑一个几千万行的核心流水表,会明显感觉到速度变慢。

3.2 命令行dexp/dimp:最灵活但要自己写清参数

第二种路径是经典的逻辑导出导入方案,用达梦自带的dexp导出,再用dimp导入。这个方案跟Oracle的exp/imp大同小异,只要掌握参数逻辑就行。

举例来说,导出整个数据库:

dexp USERID=SYSDBA/SYSDBA@localhost:5236 FILE=/dm/backup/exp.dmp FULL=Y LOG=/dm/backup/exp.log

导入到新库:

dimp USERID=SYSDBA/SYSDBA@localhost:5237 FILE=/dm/backup/exp.dmp FULL=Y LOG=/dm/backup/imp.log

这套方案最大的优势是可控性强,你可以指定模式、指定表甚至指定查询条件导出。而且因为是中间文本逻辑格式,对不同字符集之间的转换处理更灵活。缺点则是恢复时需要重建表、重建索引、重放数据,速度天然慢,不适合特别大的库。另外,跨版本升级时,如果源库中有新版本不认识的对象类型或语法,导出和导入过程中可能产生兼容性告警。

3.3 物理备份恢复dmrman:大库首选但版本匹配要小心

第三种路径是用物理备份工具dmrman做备份恢复。这个方案最接近“复制文件”的思路,速度最快,对数据一致性保障也最到位,适合数据量以T为单位的重型场景。

dmrman备份数据库的命令大致如下:

RMAN> BACKUP DATABASE '/dm/data/DMSERVER/dm.ini' FULL BACKUPSET '/dm/backup/dm7_bak';

恢复时再执行:

RMAN> RESTORE DATABASE '/dm/data/DMSERVER/dm.ini' FROM BACKUPSET '/dm/backup/dm7_bak'; RMAN> RECOVER DATABASE '/dm/data/DMSERVER/dm.ini' FROM BACKUPSET '/dm/backup/dm7_bak';

但有一点务必记住:dmrman跨大版本恢复不是你想当然的“直接认”。我用DM8版本的dmrman尝试恢复DM7的备份集,结果就遇到了“备份集格式不兼容”的报错。因为DM7和DM8的内核数据格式不一样,物理备份文件无法直接跨大版本复用。这种情况下,通常需要先用DM7的dmrman把备份集处理好,再配合官方的升级迁移工具来衔接,而不是直接用新版去还原旧版备份。

3.4 三条路径怎么选,一张表说清楚

方案工具类型适用规模跨大版本兼容性上手难度我的评价
DTS迁移工具图形化中小型库一般,报错难续传低适合初次接触达梦的迁移场景
dexp/dimp命令行中小型库较好,可指定对象中最稳妥的通用方案,我最终选用它
dmrman备份恢复命令行大型库差,物理格式绑定版本中高适合同版本补丁升级或同大版本内恢复

结合我这次的情况,数据量不算特别大,但对象的复杂度高(存储过程多、触发器多),而且涉及跨版本升级。综合考虑后,我最终选择用dexp/dimp做逻辑迁移作为主线,再用DTS作为对比校验手段。这样的组合一方面保证了迁移对象的完整性,另一方面也能在导入后用DTS做一些增量校验。

4. 实操记录:从备份恢复到应用切换的完整链路

4.1 升级前的数据库备份与环境准备

先说环境。我准备了两个达梦实例的机器,一台跑旧的DM7,端口5236;另一台规划安装新的DM8,端口5237。这样在迁移期间两个库可以并存,应用什么时候切连接,我们自己说了算,而不是被停机时间逼着走。

在旧库上执行逻辑导出:

dexp USERID=SYSDBA/SYSDBA@localhost:5236 FILE=/dm/backup/dm7_export.dmp FULL=Y LOG=/dm/backup/dm7_export.log

因为业务里存在好几个模式,我在导出时直接用了FULL=Y,把整库都导出来。这里要提醒一句,导出前最好确认一下SYSDBA账号有没有目录写权限。我当时导出的目标目录权限不对,dexp直接报错退出,排查了好一会儿才发现是权限问题,白白浪费了时间。

4.2 安装新版DM8并初始化实例

接着开始装DM8。新版安装包我在达梦官网下载,解压后执行安装向导,一路默认配置基本就能完成。不过安装完成后还有一个关键的步骤:初始化实例。

初始化实例使用的是dminit命令,我需要手动指定数据文件路径、实例名、端口号和字符集。命令大致长这样:

./dminit PATH=/dm/data DM8 INSTANCE_NAME=DMSERVER PORT_NUM=5237 CHARSET=1

这里CHARSET参数特别关键。我用的是1,代表GBK字符集,跟源库保持一致。如果这里填错了,后面导入数据很可能会导致中文乱码。如果你不确定源库到底是什么字符集,可以在旧库上执行:

SELECT * FROM v$nls_parameters;

查一下NLS字符集相关的参数,再去初始化新实例。这一步看起来不起眼,但真的决定后面导入数据的“脸色”。

初始化完成之后,通过前台方式或注册系统服务方式启动新的实例:

./dmserver /dm/data/DMSERVER/dm.ini

启动日志里出现“SYSTEM IS READY”之类的字样,就说明实例起来了。这个阶段先不要急着停旧库,让新旧两个实例并行跑着,后面的迁移才有缓冲余地。

4.3 数据导入与对象重建

接下来就是在DM8实例上执行逻辑导入:

dimp USERID=SYSDBA/SYSDBA@localhost:5237 FILE=/dm/backup/dm7_export.dmp FULL=Y LOG=/dm/backup/dm8_import.log

dimp执行的时间比dexp长不少,因为需要重建表、索引、约束和存储过程这些对象。导入过程中我特别注意日志里有没有出现错误行。实际操作中确实有几处ERROR,多数是存储过程的PL/SQL语法在新版里不兼容,还有个别表因为字符集转换导致数据长度溢出。后面第6章我会专门展开这两类问题。

导入完成后,还要做一次“二轮导入”。什么意思呢?就是说第一次导入如果有部分对象失败,你不会希望重新整库再来一遍。这时候可以先用dimp的日志筛选出失败对象,单独针对失败的模式或表重新导入,而不是动不动就全量重来。

4.4 应用侧切换与驱动更新

数据导入完成后,就不是“数据库自己跑起来”这么简单了。应用侧的连接要跟着切换,同时要核对JDBC驱动。我们这里的Java应用使用的是SpringBoot+Druid连接池,数据源配置差不多长这样:

spring: datasource: driver-class-name: dm.jdbc.driver.DmDriver url: jdbc:dm://192.168.1.20:5237/DMSERVER username: SYSTEM password: 123456

这里ip地址和端口要改成新实例的地址。如果你之前用的是旧版DmJdbcDriver,强烈建议同步升级到与新库版本匹配的驱动jar。升级驱动后还要确认Druid连接池的配置项没有变化。我曾经遇到过一种情况:驱动换了新版本之后,Druid在连接初始化时执行了一个旧驱动不支持的SQL,导致启动报错。所以切换完应用,一定要第一时间看启动日志,而不是只看看数据库连接池监控面板。

另外,如果你习惯用Navicat这类可视化工具连接达梦,升级后也要确认客户端对话框里选择的数据库版本信息是否匹配,必要时升级Navicat本身。这个点看着小,但对频繁用GUI调试的同学来说体验差异很大。

5. 升级验收清单:数据对得上,业务才敢放行

5.1 数据一致性验证:不只是行数相等

升级完最需要回答的问题是:旧库的数据到底有没有一笔不差地搬过来?

我验证的时候没有只统计表行数,因为行数一样不代表数据内容完全一致。我的做法分三步:

  • 第一步:对比每张核心表的count(*),确认总行数一致;
  • 第二步:对比若干个有代表性的字段的汇总值,比如金额字段求和、日期字段的最大最小值;
  • 第三步:做抽样明细比对,随机拉几条主键记录,在旧库和新库里分别跑同一条件查询,肉眼比一下结果。

这一步不能图省事。我当时就遇到一张日志表的行数完全一致,但其中几个长文本字段因为字符集转换被截断的情况,如果不做字段级的抽样比对,很难发现。

5.2 存储过程和作业的自检

数据对完了,接下来要验证的是“数据库里的行为逻辑”。我写了一个简单的验证脚本,把核心的存储过程挨个执行一遍,看看有没有编译错误。达梦的存储过程在创建时不会立刻报错,很多问题要到真正调用时才暴露出来,所以务必逐个调用测试。

另外,还要检查数据库作业。旧库上如果有定时作业,比如每天凌晨的清分任务,这些作业在逻辑导出导入后可能不会完整迁移过来,需要在新库中手工重建。我记得当时有一个日终调度作业,导入后作业是出现了,但对应的调度器状态不对,导致任务根本没有触发,这个如果上线前不检查,后续要等业务方反馈才会发现,就很被动了。

5.3 性能对比:不能升完级反而变慢

数据和应用层面都验证完之后,还有一道大关是性能。我的做法是挑出业务里最常用的几条SQL,分别放到旧库和新库上跑,看执行计划和耗时。在新库上如果发现执行计划走了索引,但代价计算明显不合理,可以尝试用达梦的SP_REFRESH_OPT_ENTRY这类系统包来刷新统计信息。

这里也有一个经验:升级后等待统计信息自动收集的时间可能比较长,我当时是在导入完成后主动手工执行了统计信息更新,让优化器有更准确的基数和直方图,这样后续业务方点开报表,就不会出现“为什么升级后SQL变慢”这种尴尬问题。

6. 我在这次升级中踩过的坑和排查记录

6.1 备份集跨大版本不认:别用DM8恢复DM7的物理备份

这是我最早踩的坑。一开始我图省事,想直接用DM8的dmrman去恢复DM7的物理备份,结果报错提示备份集无法识别,大致意思是版本不匹配。那一刻我才意识到,物理备份和逻辑备份的定位完全不同:物理备份的格式深度绑定版本和内核结构,跨大版本直接恢复是行不通的。

如果一定要走物理备份恢复路线,那就要清楚它更适合什么场景:相同大版本内的小版本升级,比如DM8的一个补丁版本升到另一个补丁版本。而跨大版本升级,老老实实走逻辑导出导入,或者利用官方提供的迁移评估工具,反而更稳妥。

6.2 中文乱码:根因在字符集设置

导入过程中我最头疼的是乱码问题。有个别字段导入进去之后,中文变成了一串问号“?????”。一开始我以为是导入命令参数的问题,反复调整dimp的字符集参数,发现没用。后来回头查旧库字符集,才意识到源库本身就是GBK,而新库初始化时如果不小心把CHARSET设成了别的值,导入时就会出现转码异常。

这个问题的坑在于,它不是全局性报错,而是“部分字段坏了,部分字段正常”,很容易让人误以为是随机数据损坏。后来我把新实例初始化时的字符集和源库对齐,重新导了一遍,乱码问题就消失了。

6.3 存储过程编译报错:注意内置函数差异

存储过程是这次升级里数量最多的失败对象。报错信息大多指向某些内置函数在新版中不存在,或者函数签名发生了变化。比如项目中用到的一个处理金额格式的函数,在DM7里能直接用,但在DM8里需要用另一个系统包来替代。

排查这类问题,我的做法是先把导入日志中所有ERROR信息按对象名字归类,然后逐个打开旧库和新库的对象定义做对比,确认差异点后手工修改。这个步骤没有捷径,只能耐心。如果你的项目里存储过程特别多,建议在升级前就对这些对象做一次静态扫描,把可能不兼容的函数全列出来,提前改好,要比导入后一个一个排查高效得多。

6.4 应用连接被拒:端口和加密协议都要看

升级后第一次用Navicat连接新库时,我遇到了“连接被拒绝”的情况。排查一想,发现是新实例的端口号配置不是默认的5236,而是我自定的5237,所以客户端默认连5236端口自然进不去。这个点很基础,但在紧急时刻确实容易忽略。

还有一个隐蔽的问题:新版本默认开启了更严格的通信加密要求,某些旧版本的客户端或驱动连接时会因为加密协议不匹配被拒。如果碰到这类问题,可以在dm.ini中检查通信加密相关参数,再结合客户端的版本考虑是否需要升级。

6.5 通用排查思路:先看日志,再查版本,最后复现

经历过这一圈坑,我总结出来的排查顺序基本稳定成一套:

  • 第一步,先看数据库实例的日志文件。达梦的日志一般在安装目录的log子目录下,文件名形如“dm_DMSERVER_YYYYMM.log”。很多看似莫名其妙的问题,日志里已经写得很直白。
  • 第二步,确认所有环节的版本是否在同一频道上。数据库版本、驱动版本、客户端版本、初始化参数版本,一个都不能漏。
  • 第三步,用手工操作复现问题。比如单独执行那条失败的SQL,或者单独调用那个失败的存储过程,通过最小化复现缩小排查范围。

这套思路帮我在后面处理其他数据库问题时也省了不少力。


最后再说句掏心窝的话:达梦数据库版本升级这回事,听着像是个安装活儿,实际上更像是一部“数据搬运和验证”的连续剧。你花在备份和验证上的时间,永远要比实际操作的时间多得多。我当时就是因为前期备份和兼容性评估做得足够细,才敢在正式切换的时候底气比较足。希望你也能在动手之前,先把上面这几个环节挨个过一遍。升级顺利跑通之后,再去回想整个过程,你会发现自己对达梦数据库的理解已经不是“会不会连库”的程度了,而是真的摸到了它的脾气。

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询