用了多年通用数据库,突然接到一整套“国产数据库技术”课程配套达梦 DM8 的学习任务时,我第一反应其实是有点不屑的。毕竟习惯了成熟生态的外来数据库,总觉得国产库大概率就是改个壳、抄点语法。真正啃完这套《国产数据库技术》的全程笔记,自己动手把 DM8 从安装、建库、SQL 适配、应用接入一直到备份恢复全部走了一遍之后,我必须承认:之前那种预判,多少带点偏见。达梦 DM8 在架构上是完整的关系型数据库,并且在 Oracle 兼容性上花了大功夫,同时在 MySQL 迁移、运维工具链、高可用方案上都有可落地的东西。本文就是我从零开始摸 DM8 的完整记录,把每一个决策背后的逻辑、踩过的坑、可以直接照抄的命令全部整理出来,给正在评估国产数据库或者要接手 DM8 项目的同行一个真实参考。无论你是 DBA、后端开发还是技术选型负责人,这套笔记应该都能帮你少走几天弯路。
1. 先看全局:达梦 DM8 到底是什么样的数据库
1.1 自研内核,但兼容性做了双轨
很多人的疑问是第一位的:达梦 DM8 到底是自己写的,还是基于某个开源分支改的?我在学习过程中查了不少架构资料,从官方技术白皮书和实际安装后的文件结构来判断,DM8 的底层执行引擎、存储管理、事务处理都是独立实现,不是 MySQL 或者 PostgreSQL 的分支产物。
这个判断层面的问题很重要,因为它决定了后续所有操作的思维方式。如果是基于开源库做的二次开发,那我用开源社区的经验就能直接套;但 DM8 不是,所以它的初始化工具、配置文件、系统视图、备份命令等都有自己的一套命名和逻辑。比如它没有 MySQL 那种my.cnf,而是用dm.ini作为实例配置文件;默认端口是5236;管理工具有独立的manager图形界面和disql命令行工具。这些都是自成一体的体系。
但兼容性方面,它确实参考了主流数据库的生态习惯。官方文档里明确提到兼容 Oracle 语法和 MySQL 语法两种模式,实际体验下来,Oracle 模式的完成度明显更高。很多 PL/SQL 风格的包、存储过程、数据类型在 DM8 里能找到对应物,这对从 Oracle 迁移过来的团队极其友好。MySQL 模式更多是提供一些常用函数的别名和系统行为上的模拟,毕竟 MySQL 生态也有大量用户。
1.2 它适合放在什么场景里
学完整个课程,我对 DM8 的定位有了自己的判断:它不是想在所有场景里跟主流数据库硬碰硬,而是重点解决“基础软件供应链安全”环境下,政企、金融、电力、制造等行业的核心业务替换需求。
这些场景有个共同特征:并发事务量大、数据一致性要求高、需要严格的权限管控和审计能力。DM8 的行级锁、MVCC 机制、完备的备份恢复体系、支持共享存储集群,都是冲着这些需求设计的。如果你只是做一个个人博客或者小网站,那它确实没必要;但如果你面对的是一个需要固定预算内完成国产化替代的正式项目,DM8 是非常现实的选择。
我学习时的判断框架是:先看它能不能把原业务平滑接住,再看运维和学习成本能不能承受。答案是,在兼容层做得足够好的前提下,DM8 的上手难度并没有想象中高,尤其是有 Oracle 经验的人,适应周期会非常短。
1.3 目录结构与关键进程
安装完 DM8 之后,有件事建议第一时间做:把安装目录结构和进程关系搞清楚。以我用的 Linux 环境为例,默认安装目录是/opt/dmdbms。
/opt/dmdbms/ ├── bin/ # 可执行文件,包含 disql、dmserver、dmrman 等 ├── data/ # 默认数据文件目录,包含实例目录 ├── dm.ini # 默认实例配置文件 ├── log/ # 日志目录 ├── tool/ # 管理工具,dmmanger、dmmonitor 等 └── web/ # 部分图形工具使用启动实例时,核心进程是dmserver,它会读取dm.ini里的参数完成初始化。整个数据库实例和一个操作系统进程强绑定,这点要记住,因为做启停操作的时候,经常会需要用到进程管理命令来确认状态。我习惯用ps -ef | grep dmserver来快速判断实例是否正常。
提示:DM8 对目录权限比较较真,尤其是数据目录,如果使用非 root 用户安装,务必保证该用户对数据目录有完整权限,否则启动时会报各种奇怪的权限错误。
2. 环境搭建与初始化:把第一个实例跑起来
2.1 安装前的前置检查
我在这步踩过一个典型的坑:没检查系统依赖库就开装,结果图形界面起不来,只能重新补包。在 Linux 上安装 DM8,需要先确认几个基础条件:
- 操作系统架构,x86_64 还是 ARM;不同架构要下载对应安装包。
- 内存建议至少 2GB 可用,磁盘预留 10GB 以上,因为安装包本身和解压后的文件都不小。
- 需要 glibc 等基础库,如果是精简版系统,建议用
ldd检查一下安装盘里的可执行文件依赖是否齐全。
另外,官方有图形安装、命令行安装和静默安装三种方式。我在虚拟机里第一次用的是图形安装,毕竟交互性强,适合学习;真正要批量部署的时候,静默安装才是王道。
2.2 静默安装其实更实用
图形安装没什么好说的,下一步下一步就行。静默安装的好处是参数化、可重复,适合以后在多台机器上部署。官方提供了一个配置文件模板,我按照模板改了关键路径和端口后执行:
./DMInstall.bin -q /path/to/install_conf.xml配置模板里核心是这几个参数:
<INSTALL_PATH>/opt/dmdbms</INSTALL_PATH> <INSTALL_TYPE>DATABASE</INSTALL_TYPE> <PORT>5236</PORT> <DB_NAME>DAMENG</DB_NAME> <DB_INSTANCE_NAME>DMSERVER</DB_INSTANCE_NAME> <SYSDBA_PWD>SYSDBA001</SYSDBA_PWD>注意,这里的SYSDBA_PWD是数据库超级管理员密码,不是操作系统密码。安装完成之后一定要立刻改默认密码,这属于最基本的安全习惯,课程里反复强调,实际生产也是如此。
注意:静默安装完成后,默认会创建一个名为 DAMENG 的数据库实例,初始化参数是默认的。如果你对页大小、字符集有特殊要求,后面建库时要用工具重新创建实例。
2.3 初始化实例的关键参数选择
DM8 的实例创建可以用图形化的“数据库配置助手”,也可以用命令行。我更推荐命令行,方便记录和复现。
初始化实例时,有两个参数必须提前想清楚,因为建库之后很难修改:
第一个是PAGE_SIZE,页大小。DM8 支持 4K、8K、16K、32K 的页大小。页大小会直接影响单行最大长度、表空间文件最大大小以及数据库的整体 I/O 行为。默认 8K 对绝大多数业务是合适的;但如果你的业务涉及大字段、超长字符串,建议直接上 16K。我在模拟项目 X 里因为一开始用了默认 8K,后面设计表时发现某些 VARCHAR 长度组合放不下,只能重建库,非常折腾。
第二个是字符集。DM8 默认是 GB18030,这是在中文 Windows 等环境下的老传统,但对现代业务来说,UTF-8 是更通用且避免乱码的选择。我建议直接选UTF-8。
命令行方式创建实例如下:
cd /opt/dmdbms/bin ./dminit PATH=/opt/dmdbms/data DM_INI=/opt/dmdbms/data/DAMENG/dm.ini \ PAGE_SIZE=16 CHAR_CODE=UTF8 CASE_SENSITIVE=0这里我额外设置了CASE_SENSITIVE=0,意思是标识符大小写不敏感。这个参数很影响使用体验。默认情况下 DM8 是大小写敏感的,如果你从 MySQL 迁过来,表名字段名习惯用大写或者小写,很容易被这个坑到。对大多数业务应用,关掉大小写敏感会更顺手。
2.4 服务注册与启停
初始化完成后,需要把数据库注册成系统服务,或者至少知道怎么手动启停。手动方式最简单,直接调dmserver:
cd /opt/dmdbms/bin ./dmserver /opt/dmdbms/data/DAMENG/dm.ini前台运行的方式适合调试,因为日志会直接打到终端,能第一时间看到启动错误。确认正常后,我习惯注册成服务,用项目里提供的脚本:
cd /opt/dmdbms/script/root ./dm_service_installer.sh -t dmserver -p DMSERVER -dm_ini /opt/dmdbms/data/DAMENG/dm.ini之后就能用systemctl start DmServiceDMSERVER这类命令管理了。
3. 用户的创建与权限体系:迈过入门第一道坎
3.1 DM8 的默认用户,不能只会用 SYSDBA
DM8 安装后自带几个默认用户,这是很多新手最容易懵的地方。默认用户里最重要是下面这几个:
| 用户名 | 作用 | 说明 |
|---|---|---|
| SYSDBA | 超级管理员 | 拥有数据库几乎所有权限 |
| SYSSSO | 安全管理员 | 管理安全策略、审计 |
| SYSAUDITOR | 审计员 | 查看审计记录 |
| SYS | 系统用户 | 持有系统表、字典 |
| SYSTEM | 系统用户 | 部分系统对象 |
我第一次学的时候,习惯性拿 SYSDBA 开干所有事,后来课程里特别提醒:正式项目不能这么干。DM8 的三权分立设计,本质是让 DBA、安全管理员、审计员角色分离,避免一个人权力过大。虽然小项目不一定要分这么细,但至少应该给应用建独立的业务账号,而不是拿 SYSDBA 连接业务应用。
建用户的标准操作:
CREATE USER app_user IDENTIFIED BY "App@123456"; GRANT CREATE SESSION, CREATE TABLE TO app_user; GRANT SELECT, INSERT, UPDATE, DELETE ON schema_name.business_table TO app_user;3.2 表空间:从创建到配额
表空间是数据库存储的逻辑单位,每个用户最好都指定默认表空间。我在课程中养成的习惯是,一个业务域一个表空间,数据文件独立,这样后续做备份恢复的粒度会很清晰。
CREATE TABLESPACE TS_APP DATAFILE '/opt/dmdbms/data/DAMENG/TS_APP.DBF' SIZE 2048 AUTOEXTEND ON NEXT 128 MAXSIZE 8192; ALTER USER app_user DEFAULT TABLESPACE TS_APP;这里要提醒一个细节:DM8 表空间数据文件大小受页大小影响,页大小 8K 时单个数据文件最大约 32GB,16K 页时最大约 64GB。如果建库时就预期数据量很大,直接选 16K 或 32K 页,后面省心。
3.3 角色与最小权限原则
DM8 内置了几种常用角色,比如DBA、RESOURCE、CONNECT。这些角色解决的是批量授权问题,但我实际操作后强烈建议,宁可多写几条GRANT语句,也不要图省事直接给业务用户DBA角色。国产化项目通常对安全审计有要求,最小权限原则既是规范,也是自保。课程里有个生动的例子:某项目因为给报表账号开了 DBA 权限,后来排查数据问题时,审计记录里分不清是谁动了表,责任界定的麻烦远远大于临时授权的便利。
4. SQL 实战:从建表到业务逻辑迁移
4.1 数据类型和建表习惯
DM8 数据类型整体上非常接近 Oracle:NUMBER、VARCHAR2、CLOB、BLOB都能直接用。同时它也支持 MySQL 风格的类型写法,比如INT、VARCHAR。这给迁移带来了极大的方便,但也会造成一个问题:相同名称的类型,底层行为可能不完全一致,比如VARCHAR的默认长度单位、是否支持 0 长度等。
我建表时采用的策略是:从 Oracle 迁移的表,保持原类型不动;从 MySQL 迁过来的表,全部统一改成 DM8 的 Oracle 风格类型。虽然前期要花点时间做转换,但这能避免后续 SQL 写法出现隐式行为不一致。
一个典型的建表示例:
CREATE TABLE T_ORDER ( ORDER_ID NUMBER(18) PRIMARY KEY, ORDER_NO VARCHAR2(32) NOT NULL, CUSTOMER_ID NUMBER(12), ORDER_AMOUNT NUMBER(12,2), STATUS CHAR(1) DEFAULT '0', CREATE_TIME TIMESTAMP DEFAULT CURRENT_TIMESTAMP, REMARK VARCHAR2(500) ); CREATE INDEX IDX_ORDER_CUST ON T_ORDER(CUSTOMER_ID); CREATE INDEX IDX_ORDER_TIME ON T_ORDER(CREATE_TIME);注意,DM8 的注释语句是COMMENT ON COLUMN T_ORDER.ORDER_NO IS '订单号';,和 MySQL 那种行内COMMENT '订单号'不同,做迁移脚本的时候要转换。
4.2 常用 SQL 写法差异对照
这部分是干货中的干货。我把自己平时最常用的一些 SQL 写法在 DM8 和其他主流数据库之间做了对照:
| 功能 | MySQL/其他写法 | DM8 写法 |
|---|---|---|
| 分页查询 | LIMIT 10 OFFSET 20 | SELECT ... LIMIT 10 OFFSET 20; 也支持 ROWNUM 写法 |
| 字符串拼接 | CONCAT(a, b) 或 | |
| 当前日期 | NOW() | SYSDATE 或 NOW() |
| 自增列 | AUTO_INCREMENT | IDENTITY(1,1) 或序列+触发器 |
| 空值排序 | NULLS FIRST/LAST 取决于数据库 | 默认 NULL 最大 |
| 批量插入 | INSERT INTO ... VALUES (...), (...) | 支持多表值 INSERT,也支持 INSERT ALL |
实际操作中,分页查询我倾向于直接用LIMIT/OFFSET风格,因为很多从互联网业务转过来的开发熟悉这种写法。但如果 SQL 已经用了 Oracle 的ROWNUM,DM8 也兼容。
4.3 存储过程:迁移大头
存储过程是 DM8 兼容性的主力战场。我建议拿一个真实的存储过程做测试,比看十页文档都有效。以我测试的一个示例存储过程为例:
CREATE OR REPLACE PROCEDURE P_UPDATE_ORDER_STATUS( v_order_id IN NUMBER, v_new_status IN CHAR ) AS v_cnt NUMBER; BEGIN SELECT COUNT(*) INTO v_cnt FROM T_ORDER WHERE ORDER_ID = v_order_id; IF v_cnt = 0 THEN RAISE_APPLICATION_ERROR(-20001, '订单不存在'); END IF; UPDATE T_ORDER SET STATUS = v_new_status WHERE ORDER_ID = v_order_id; COMMIT; EXCEPTION WHEN OTHERS THEN ROLLBACK; RAISE; END;这个写法从 Oracle 迁移过来几乎不用改。DM8 支持RAISE_APPLICATION_ERROR、EXCEPTION、自治事务PRAGMA AUTONOMOUS_TRANSACTION等,PL/SQL 的大部分能力都有对应实现。这也是为什么很多 Oracle 背景的项目选择 DM8 时,存储过程迁移成本极低。
4.4 数据装载与导出:dmfldr 和 disql
数据迁移绕不开批量导入导出。DM8 提供了图形工具“数据迁移工具”,可以从其他数据库直接迁。但我的经验是,大批量数据在场内做装载时,用命令行工具dmfldr更高效。
dmfldr的作用类似 Oracle 的sqlldr,用法也很直白。假设我有一个/tmp/order_data.csv,字段之间用逗号分隔:
cd /opt/dmdbms/bin ./dmfldr USERID=app_user/App@123456 CONTROL='/tmp/load.ctl' DATA='/tmp/order_data.csv'控制文件load.ctl内容示例:
LOAD DATA INTO TABLE T_ORDER FIELDS TERMINATED BY ',' TRAILING NULLCOLS ( ORDER_ID, ORDER_NO, CUSTOMER_ID, ORDER_AMOUNT, STATUS )这个工具我实测下来,百万行级别的数据导入是分钟级,比用图形界面或者逐条 INSERT 好了太多。导出方面,dexp和dimp是逻辑备份导入导出工具,类似于 Oracle 的exp/imp,后面备份章节会说。
5. 备份恢复与一致性:DBA 能力的关键试金石
5.1 备份方式全景
DM8 的备份体系完整,物理备份、逻辑备份都有。我建议按场景区分使用:
| 需求 | 推荐工具 | 说明 |
|---|---|---|
| 数据库全量物理备份 | DMRMAN 或 disql 内 BACKUP 命令 | 恢复速度快,适合正式环境 |
| 增量物理备份 | DMRMAN | 可以基于某个备份集做增量 |
| 逻辑导出 | dexp | 适合迁移、小数据量逻辑备份 |
| 逻辑导入 | dimp | 对应 dexp 的导入端 |
物理备份推荐用DMRMAN工具,这是 DM8 的备份恢复命令行工具,功能比较全。做了全量备份和增量备份之后,它能维护一个备份集,恢复时可以基于这个备份集做完整恢复。
5.2 备份实操记录
我第一次做备份时,图形界面点了几下就完事了,后来发现命令行下更可控。全量备份命令如下:
cd /opt/dmdbms/bin ./dmrman CTLFILE=/opt/dmdbms/data/DAMENG/dm.ini进入 dmrman 交互界面后执行:
BACKUP DATABASE '/opt/dmdbms/data/DAMENG/dm.ini' FULL BACKUPSET '/backup/dm_full_20250101';这条命令生成一个全量备份集。增量备份则是在全量基础上执行:
BACKUP DATABASE '/opt/dmdbms/data/DAMENG/dm.ini' INCREMENT BACKUPSET '/backup/dm_inc_20250102';增量备份必须指定在上一次备份之后执行,DMRMAN 会自动追踪备份链。这里有一个踩坑记录:备份路径所在文件系统剩余空间不够,会导致备份失败,而且 DM8 的报错提示信息在早期版本里不够直观,只提示“磁盘空间不足”。所以做备份前先df -h检查磁盘,是职业习惯。
5.3 恢复流程:把实例恢复到指定时间点
恢复的思路是,先还原数据文件,再恢复日志或增量备份。用 DMRMAN 恢复到某个时间点的操作大致如下:
RESTORE DATABASE '/opt/dmdbms/data/DAMENG/dm.ini' FROM BACKUPSET '/backup/dm_full_20250101'; RECOVER DATABASE '/opt/dmdbms/data/DAMENG/dm.ini' FROM BACKUPSET '/backup/dm_inc_20250102'; RECOVER DATABASE '/opt/dmdbms/data/DAMENG/dm.ini' UPDATE DB_INFO;完整恢复流程的执行顺序很重要,如果顺序反了,DMRMAN 会报备份集不匹配,可能还需要重新还原。我的练习方法是:先备份,然后往库里塞一堆测试数据,再模拟删库,最后完整走一遍恢复流程,检查数据是否回到了备份点。这样整套流程跑顺之后,心里才真正有底。
5.4 高可用:主备与共享存储集群
课程里还简单介绍了 DM8 的高可用方案。主备架构下,主库负责读写,备库通过日志同步保持数据一致,安装配置比裸跑实例复杂一些,但核心思想并不难理解。做容灾演练的时候,我学到最重要的一句话是:“备份是最后一道防线,高可用是缩短恢复时间的手段,两者不能互相代替。”不管用主备还是共享集群,日常备份都不能省。
6. 实战中的疑难杂症与调优记录
6.1 连接不上数据库,先别急着怀疑密码
我一共遇到过三次连接失败,其中两次都是实例没起来。DM8 的dmserver进程崩掉或未启动时,客户端会报“网络通信异常”,但这容易让人误以为 IP、端口或者防火墙问题。排查顺序建议是:
ps -ef | grep dmserver ss -lntp | grep 5236先确认进程和端口都在,再去检查连接串。这个顺序能省大量排查时间。如果进程死掉了,去看实例目录下的日志,重点搜ERROR关键字,多半能直接定位问题。
6.2 中文乱码:字符集不匹配是元凶
乱码问题在国产数据库课程里几乎必被提到。根源通常出在两端:数据库字符集和客户端字符集不一致。我之前在 DM8 建库时选了 GB18030,但应用端连接的字符集是 UTF-8,插入中文后查询直接出乱码。
解决方案有两种:第一种最直接,重建库时把字符集改成 UTF-8,一劳永逸;第二种是在 JDBC 连接串上指定encoding=GBK或者UTF-8参数,但这是治标不治本。涉及多套系统协作时,标准做法就是全局统一 UTF-8。
6.3 慢 SQL 分析与执行计划
DM8 查看执行计划的方式和 Oracle 很像,可以在 disql 里打开执行计划开关:
SET AUTOTRACE ON; SELECT * FROM T_ORDER WHERE CUSTOMER_ID = 12345;也可以在 SQL 前加EXPLAIN关键字查看计划。我调优时最常用的几个方向:
- 确认索引是否被正确使用,有没有发生不必要的全表扫描。
- 确认条件字段的类型与索引字段类型是否一致,类型隐式转换会导致索引失效。
- 确认统计信息是否过期。DM8 在某些自动更新统计信息方面没有主流数据库积极,大表数据量明显变化后,我会手动执行
DBMS_STATS.GATHER_TABLE_STATS('APP_USER', 'T_ORDER');来更新统计信息。
一个真实记录:生产环境某条查询之前毫秒级响应,后来数据量涨了百倍后直接秒级。排查发现旧统计信息里表行数还停留在一万级别,优化器选择了错误执行计划。分析后手动收集统计信息,并重建了一个组合索引,查询恢复到了 50 毫秒以内。
6.4 内存参数调整
DM8 实例的内存参数分成了很多池,比如缓冲区BUFFER_SIZE、日志缓冲区等。最影响性能的一个是数据缓冲区BUFFER_SIZE。配置在dm.ini中,修改后需要重启实例生效。
我一般先看监控数据,如果缓冲区命中率持续过低,再逐步调大:
cd /opt/dmdbms/bin ./disql SYSDBA/SYSDBA001 SQL> SELECT name, VALUE FROM V$PARAMETER WHERE NAME LIKE '%BUFFER%';调整策略是让数据库整体缓冲区命中率保持在 95% 以上。如果命中率很低,先别急着加内存,可能更应该优化 SQL 和索引逻辑。
7. 一些值得长期坚持的习惯
整套课程学完,我有一个很深的体会:达梦 DM8 不缺功能,缺的是使用者的心态转换。习惯了 MySQL 的人会觉得它部分系统表的写法别别扭扭,习惯了 Oracle 的人又会拿它跟正版 Oracle 比较,觉得这里不如那里不熟。但实际上,评价一个国产数据库是否可用,关键不在它与某一款数据库的相似度有多高,而在于它在你具体的业务场景里能不能稳定、安全、可控地运转。
我在学习后期的做法是,把 DM8 当成一个独立产品来对待,而不是某个数据库的仿制品。遇到不熟悉的语法,先查官方手册;遇到迁移问题,先用小数据量测试;遇到性能瓶颈,认真分析执行计划而不是盲目加内存。数据库没有什么玄学,所有问题最后都能落到架构、配置、SQL、数据分布这几个硬因素上。
如果你正准备学 DM8,我个人强烈建议把课程里每一个练习都动手操作一遍,尤其是备份恢复和权限管理,光看不练容易眼高手低。另外,用达梦的迁移工具做一次真实的业务库迁移实验,比看十篇对比文章都管用。这东西说到底就是个工具,判断一个工具好不好,拿起来干一把活最直接。