
这两年做数据库相关工作的同行应该都有一个很直观的感受信创、国产化迁移的需求明显多了起来。我自己经手的项目里达梦DM8是接触最多的一款国产数据库很多原本跑在Oracle上的系统最终都迁移到达梦上。这篇就当一次实战总结从零开始走一遍达梦DM8全流程先聊清楚它是什么、适合什么场景再一步步把环境搭起来、把表空间和用户建好重点讲讲性能优化具体怎么做最后把我在真实项目里踩过的坑和排查经验一并倒出来。全文会给出可复制的命令和SQL从环境搭建到性能优化都有实例代码有一定数据库基础的朋友可以直接照着操作。1. 项目背景与选型思路1.1 达梦DM8到底是什么达梦数据库管理系统简称DM8是当前主流的大版本。它属于关系型数据库核心引擎是自研的但语法体系上大量兼容Oracle——这对无数从Oracle迁移过来的系统来说意义非常大。很多人会问它和MySQL像还是和Oracle像答案是它在使用习惯上更接近Oracle。存储过程、触发器、包、序列、物化视图、同义词这些概念都有SQL层面NVL、DECODE、ROWNUM这些Oracle风格的函数也都能直接用甚至很多管理视图的名字都和Oracle一致。这在项目中带来的一个巨大好处是迁移成本低。我参与过的一个某单位的业务系统原来跑在Oracle上改到达梦后90%以上的SQL不用动剩下改动的主要集中在少数不兼容的函数和分页写法上。对于开发人员和DBA来说学习曲线非常友好基本上一两天就能上手干活。而如果你之前只玩过MySQL那可能要稍微适应一下因为达梦没有information_schema那种习惯换成了V$字典视图和DBA_视图观念上需要切换。1.2 为什么选择它场景与取舍选数据库这件事不能光看跑分。我从几个维度聊聊达梦在真实项目里的优势。合规与国产化是大前提。很多项目合同里直接写明了要使用国产数据库达梦是能拿到相关资质认证的政企、金融、能源类项目尤其常见。Oracle兼容性做得比较到位。底层存储过程、SQL语法、工具链都有意识地往Oracle靠迁移团队的工作量能显著下降。部署形态灵活支持单机、主备、读写分离集群、共享存储集群等单机和主备模式在中小项目中部署起来不复杂。运维习惯友好如果你熟悉Oracle上手达梦几乎没有障碍很多命令、字典视图可以直接套用。当然任何数据库都有自己的短板。达梦的社区生态、第三方中间件适配范围确实不如MySQL和PostgreSQL那么庞大网上能搜到的中文资料质量也参差不齐。所以在选型时要把团队技能树、项目周期都考虑进去。我的原则是项目有明确国产化要求或者本来就要从Oracle迁移优先考虑达梦如果是全新互联网高并发业务、没有历史包袱那更应该认真比较MySQL、PG这类生态更成熟的产品。数据库选型这种事没有绝对最好只有适不适合当前场景。2. 环境搭建从零开始部署 DM82.1 部署前的环境检查清单我在安装前一般会先做一个静默检查避免装到一半才发现环境不行。核心就几项第一是操作系统。主流Linux发行版基本都支持CentOS 7/8、统信UOS、麒麟等都是常见承载环境。官方文档里有具体支持矩阵动手前最好先看一眼别在系统兼容性上浪费一整天。第二是硬件资源。内存建议至少2GB以上生产环境8GB起步比较合理磁盘先想好数据放在哪路径规划好别装完发现空间不够。数据库这种活磁盘和内存永远不嫌多。第三是依赖库。比如libaio、glibc、ncurses等基础库要装齐少一个可能导致安装程序或数据库启动时报错。用dmdba用户部署是比较规范的做法。注意安装数据库不要用root日常运维也别用root去连数据库。第一步先建用户和组groupadd dinstall useradd -g dinstall -m -d /home/dmdba dmdba passwd dmdba然后调整资源限制否则实例容易因为打开文件数、进程数不够而异常。通常在 /etc/security/limits.conf 里加dmdba soft nofile 65536 dmdba hard nofile 65536 dmdba soft stack 32768 dmdba hard stack 32768改完后最好重新登录dmdba用户用ulimit -n验证一下是否生效。这一步看起来不起眼但我在生产环境里遇到过不止一次因为文件句柄不够导致dmserver进程被系统杀掉的故障根源就是初始环境配置没做。2.2 安装介质与安装方式达梦提供图形化和命令行两种安装方式。服务器上我几乎都用命令行方式因为很多环境没有图形界面而且命令行更可控。安装包一般是一个DMInstall.bin文件有的版本也叫dm8_xxx.iso需要先挂载。假设已经上传并解压到了某个目录直接执行cd /opt/dm_install/ chmod x DMInstall.bin ./DMInstall.bin -q静默安装过程中会提示输入安装路径、组件等。如果你不想交互也可以准备一个response文件来指定安装路径和组件。我的习惯是安装到 /dm8 这种独立目录不用系统默认路径方便后续维护和备份。安装过程最后会提示用root执行一个脚本来完成一些系统级配置按它的提示做就行。安装完成后关键目录结构大概是这样的路径作用/dm8/bindmserver、disql、dminit 等可执行程序/dm8/script/root需要root权限的服务注册等脚本/dm8/log安装与运行日志这里有一点要特别注意达梦的安装和实例是分开的。安装只是把软件装好真正干活的是后面用dminit初始化出来的实例类似于Oracle中“软件安装”和“建库”两个阶段。我第一次弄的时候差点在这上面绕晕以为装完软件就能直接连库结果半天连不上。2.3 初始化实例与关键参数选择实例初始化用dminit这一步是最容易出问题的。先切到dmdba用户写清楚PATH和数据目录su - dmdba cd /dm8/bin ./dminit PATH/dm/data/DMDB \ DB_NAMEDMDB \ INSTANCE_NAMEDMSERVER \ PORT_NUM5236 \ PAGE_SIZE16 \ EXTENT_SIZE16 \ CHARSET1 \ CASE_SENSITIVEY说说这些参数为什么重要。PAGE_SIZE是页大小直接影响一行数据能写多长、索引性能以及整个库的容量上限。一般业务系统选8KB或16KB一旦建库后不能改所以前期要想好别后面悔。CHARSET控制字符集跨系统协作多的场景我强烈建议UTF-8否则中文乱码会折腾到怀疑人生。CASE_SENSITIVE是大小写敏感标志它决定了表名、列名不带引号时是否强制大写。很多从MySQL迁过来的同事第一周就栽在这里后面我会单独讲。初始化完成后数据目录 /dm/data/DMDB 下会生成dm.ini、系统表空间文件、日志文件等。整个库的数据文件都在这个目录里备份也好、迁移也好先认准这个目录别每次找半天。2.4 注册服务、启停与连接验证初始化只表示实例“存在”要让它像系统服务一样随开机启动需要用root执行服务注册脚本/dm8/script/root/dm_service_installer.sh -t dmserver \ -p DMSERVER \ -dm_ini /dm/data/DMDB/dm.ini注册成功后就能用systemctl统一管理systemctl start DmServiceDMSERVER systemctl status DmServiceDMSERVER systemctl enable DmServiceDMSERVER服务名一般是 DmService 加上实例名所以这里是DmServiceDMSERVER。启动完可以用达梦自带的命令行工具disql验证连接/dm8/bin/disql SYSDBA/你的密码localhost:5236能进到 SQL 提示符说明实例和服务都正常了。第一次连上建议先看版本信息和关键环境SELECT * FROM V$VERSION; SELECT NAME, CREATE_TIME FROM V$DATABASE;到这儿一个最小可用环境就搭起来了。整个流程如果用熟了在Linux上装一个达梦实例熟练工十几分钟就能搞定。很多人觉得国产数据库部署复杂其实按步骤走下来并不比装其他数据库慢多少。3. 实操基本功表空间、用户与SQL3.1 表空间规划与数据文件管理达梦的存储体系跟Oracle很像数据库由若干表空间组成每个表空间对应磁盘上的一个或多个数据文件。默认表空间里有SYSTEM、ROLL、MAIN、TEMP等SYSTEM放系统数据ROLL放回滚信息TEMP是排序等临时空间。但正规项目里我一般不建议把业务数据直接塞到MAIN或SYSTEM里而是自己单独建业务表空间这样便于管理和迁移。CREATE TABLESPACE TS_APP DATAFILE /dm/data/DMDB/TS_APP01.DBF SIZE 512 AUTOEXTEND ON NEXT 128 MAXSIZE 4096;注意这里数据文件的路径必须放在实例能访问到的目录下。如果目录不存在要先mkdir并确认dmdba用户有写权限否则建表空间会报错。管理上常用这些查询SELECT TABLESPACE_NAME, STATUS, TOTAL_SIZE * PAGE_SIZE / 1024 AS TOTAL_MB FROM V$TABLESPACE;日常巡检里我最关注的就是表空间使用率。数据文件如果开的是定长不自动扩展业务高峰期很容易一秒钟把空间撑满整个库直接卡住。所以我的习惯是核心业务表空间全部开启AUTOEXTEND并且设置合理的MAXSIZE上限既避免手工频繁扩容又能防止某个失控SQL把磁盘写爆。3.2 用户与权限体系建完表空间接下来就是建用户。达梦里用户和模式的关系需要提前说清楚在SQL里写user.table实际上就是“用户名下的模式下的表”所以一个用户默认拥有与自己同名的模式。最常用的授法是给应用单独建用户再把默认表空间指到业务表空间CREATE USER APP_USER IDENTIFIED BY 你的强密码 DEFAULT TABLESPACE TS_APP; GRANT RESOURCE TO APP_USER; GRANT CONNECT TO APP_USER; ALTER USER APP_USER DEFAULT TABLESPACE TS_APP;如果项目里需要管理员角色可以直接GRANT DBA但生产环境我建议按最小权限原则来别不管三七二十一给全体应用账号发DBA。尤其是数据库账号密码很容易被写进配置文件里权限越大的账号泄露风险越高。我在审计一个存量系统时发现几乎所有应用账号都是DBA权限后来花了很大力气才逐步收紧。3.3 建表与分区表实战写法建表语法和Oracle高度一致但有一个坑值得单独提醒大小写敏感。如果初始化时CASE_SENSITIVEY那你写的表名、字段名都会默认转成大写想保留小写必须给对象名加双引号。下面这段是兼容Oracle风格的建表语句CREATE TABLE T_ORDER ( ORDER_ID INT, ORDER_NO VARCHAR(32), ORDER_DATE DATE, AMOUNT DECIMAL(12,2), STATUS CHAR(1), CONSTRAINT PK_ORDER PRIMARY KEY (ORDER_ID) ); CREATE INDEX IDX_ORDER_DATE ON T_ORDER(ORDER_DATE);对于有明显时间维度的业务表我强烈建议上分区表。后续清理数据和查询效率都会好很多CREATE TABLE T_ORDER_PART ( ORDER_ID INT, ORDER_DATE DATE, AMOUNT DECIMAL(12,2) ) PARTITION BY RANGE(ORDER_DATE) ( PARTITION P2024 VALUES LESS THAN (2025-01-01), PARTITION P2025 VALUES LESS THAN (2026-01-01), PARTITION P2026 VALUES LESS THAN (2027-01-01) );分区并不会让单条SQL变魔法快很多它的核心价值是分区裁剪和利于滚动清理。例如丢掉一整年数据时直接drop partition远比delete上亿行数据快。我接手过一个6亿行的流水表每个月清理一次历史数据用分区方案后清理操作从小时级变成分钟级。3.4 DBA日常调试SQL与常用字典如果你之前玩的是MySQL突然切到达梦最不习惯的可能是找不到information_schema。达梦的奥义是V$字典视图加DBA_视图。像这样-- 查看所有会话 SELECT USERNAME, STATE, SQL_TEXT, LAST_SEND_TIME FROM V$SESSIONS ORDER BY LAST_SEND_TIME DESC; -- 查看锁等待 SELECT * FROM V$LOCK WHERE BLOCKED 1;连进来之后先熟悉两个函数会非常有用SF_GET_PARA_VALUE和SF_SET_PARA_VALUE。前者查看运行参数后者动态修改参数。配数据库参数的时候用它们能少重启很多次。另外如果你开启SQL日志慢SQL记录在实例目录的log下出问题时用文本工具一翻就能定位。不要小看这些基本功DBA排查问题快不快很大程度上取决于对字典视图熟不熟。4. 性能优化实战4.1 内存与并发参数调整数据库性能优化的第一刀应该落在内存和并发上。达梦的核心参数都写在dm.ini里运行时可以用管理函数查看和调整。我习惯先看现状再动刀SELECT SF_GET_PARA_VALUE(1, BUFFER_POOL_SIZE) AS BUFFER_MB; SELECT SF_GET_PARA_VALUE(1, SESSIONS) AS SESSIONS;这里说几个我常调的参数。BUFFER_POOL_SIZE是数据页缓冲池大小单位MB。缺省可能偏小如果是专用数据库服务器且内存充裕我会把70%到80%的可用内存分给数据库相关缓冲然后根据业务类型微调。这个参数对查询性能影响非常直接命中率上去了磁盘IO压力立刻下降。SESSIONS是最大会话数。连接数打满会导致新的连接直接失败踩过坑的都懂。建议结合应用连接池大小估算应用连接池最大连接数乘以应用实例数再留1.5倍左右的余量。LOG_BUF_SIZE是日志缓冲区大小写密集型系统适当调大能减少日志文件写入的IO次数。修改时区分动态和静态参数。比如SESSIONS这类往往需要改dm.ini重启生效BUFFER_POOL_SIZE有些版本支持动态调整。稳妥做法是修改前先备份dm.ini能动态就动态不能动态就规划好维护窗口重启实例。ALTER SYSTEM SET BUFFER_POOL_SIZE 2048; -- 或者 SP_SET_PARA_VALUE(1, BUFFER_POOL_SIZE, 2048);这两种写法在不同版本里支持情况不完全一样建议以你手里的版本的实际返回结果为准多看V$DM_INI视图确认参数生效状态。千万别在文档没确认的情况下在生产库上乱改一次参数调错导致重启失败的教训够喝一壶的。4.2 索引设计与优化索引是最常见也最容易见效的优化手段。达梦支持B树索引、位图索引、全文索引等日常业务OLTP系统用B树就够了。我在项目中总结过几条索引设计原则。第一优先关注高频WHERE条件字段尤其是等值查询字段。第二组合索引的字段顺序要按区分度从高到低排而不是随手把查询条件按书写顺序放进去。第三不要在一块表上堆几十个索引写入变慢不说索引本身也占空间。遇到过最典型的案例是一张几千万行的订单表查询条件经常是status加order_date原系统只有一个主键索引每次查都走全表扫描。加了一个组合索引之后查询从十几秒降到毫秒级。SQL如下CREATE INDEX IDX_ORDER_STATUS_DATE ON T_ORDER(STATUS, ORDER_DATE);注意索引不是越多越好。特别是字段找不到唯一性的时候该考虑的是怎么写SQL而不是盲目加索引。另外达梦里很多跟Oracle相同的经验是通用的避免在索引列上做函数运算避免隐式类型转换这些都是老生常谈但在实际代码里真的很容易犯。比如WHERE TO_CHAR(ORDER_DATE)2025-01-01这种写法一旦在索引列上套了函数索引基本就废了改成范围判断会好得多。4.3 SQL执行计划与统计信息当一条SQL慢下来第一件事不是瞎猜而是看执行计划。达梦里用EXPLAIN就能看到计划EXPLAIN SELECT * FROM T_ORDER WHERE STATUS1 AND ORDER_DATE 2025-01-01;看计划时重点关注几个信号有没有走全表扫描、有没有用对索引、关联顺序是否合理、排序和哈希操作是否在数据量极大的情况下出现。这些迹象直接提醒你到底该改SQL还是改索引。另一个极容易被忽略的点是统计信息。如果优化器拿到的统计信息是旧的即使有索引也可能不走。建议业务表的数据变化较大后定期收集一下统计信息DBMS_STATS.GATHER_TABLE_STATS(APP_USER, T_ORDER); DBMS_STATS.GATHER_INDEX_STATS(APP_USER, IDX_ORDER_STATUS_DATE);收集统计信息和生成执行计划这两件事配合起来往往比单纯调参数更立竿见影。我之前接手过一个系统查询一会快一会慢后来发现是统计信息长期没人管优化器在走错路。后来加了每周定时任务统一收集一轮问题就消停了。很多所谓“灵异性能问题”最后查下来基本都是统计信息过期闹的。4.4 监控手段与AWR报告达梦提供了类似于Oracle AWR的性能报告功能叫AW工作负载仓库。常用套路是先拍快照再生成报告-- 创建快照 CALL DBMS_WORKLOAD_REPOSITORY.CREATE_SNAPSHOT(); -- 查看已有快照 SELECT SNAP_ID, BEGIN_INTERVAL_TIME FROM SYS.WRM$_SNAPSHOT ORDER BY SNAP_ID;报告生成一般在安装目录的tool或bin下有对应脚本导出成文件后可以直接看Top SQL、等待事件、内存走势。第一次接触的人不用把报告所有部分都读一遍优先看三个地方最耗时的SQL、Buffer命中率、等待事件排行。很多故障苗头在真正发生前其实都藏在报告数字里。还有一种成本很低的做法就是开启系统SQL日志把慢SQL记录到日志文件里出问题时翻日志定位。生产环境注意控制日志级别和大小避免日志本身反过来成为性能负担。我有一次就是启了全量SQL日志没管结果日志文件疯狂增长把磁盘塞满最后数据库直接停机。日志功能是好东西但一定要配上日志轮转和保留策略。5. 常见问题与排查技巧记录5.1 启动与连接类故障实例启动失败最常见的原因是内存不足或者dm.ini参数配置错误。先看日志tail -100 /dm/data/DMDB/log/dm_dmserver_*.log启动失败日志一般会直接告诉你原因比如not enough memory或者某个路径不存在。我遇到一次是安装后没调整ulimit限制dmserver刚启动就被系统杀掉了后来把nofile调大才解决。排查时顺手执行df -h和free -m确认磁盘和内存别在日志里绕半天。连接不上数据库先确认三件事服务进程在不在、端口通不通、账号密码对不对。服务没了就启动服务端口不通往往是防火墙拦住了5236端口firewall-cmd --zonepublic --add-port5236/tcp --permanent firewall-cmd --reload连接数打满。错误提示大概会是too many sessions之类的。排查当前连接数并确认瓶颈SELECT COUNT(*), STATE FROM V$SESSIONS GROUP BY STATE;如果历史上来没这么多连接看看应用连接池是不是泄露了。如果确实是业务增长就要评估SESSIONS参数并合理扩容。这类问题定位起来不难难的是别把SESSIONS一味调大而不去处理连接池泄漏那样只会让问题以更隐蔽的方式继续存在。5.2 性能类故障一条SQL跑着跑着突然慢了。优先级最高的排查路径是统计信息过期、执行计划被缓存带歪、锁等待、系统资源被占满。可以先用V$SESSIONS看会话等待什么再看V$LOCK有没有锁等待必要时对相关表重新收集统计信息。从其他数据库迁移过来的乱码或报错问题多数是字符集初始化不一致导致的。达梦实例、客户端工具、数据库表字符集三者的设置要统一。我个人建议所有新库初始化时直接指定UTF-8数据交换、Web显示都会省心很多。这个建议在MySQL那边同样适用但达梦这个坑踩一次就够了别在初始化时图省事随便选个编码。5.3 几个非常实用的踩坑心得大小写敏感是新手最常掉进去的坑。初始化时CASE_SENSITIVEY你建的APP_USER表不带引号访问其实是APP_USER.T_ORDER全部转大写如果应用代码里用驼峰或小写写表名且没有统一大写规范就会莫名报无效的表名或视图名。遇到这种情况先看建库参数再统一代码里的对象命名。这个坑在建模阶段就要想清楚否则后期改库参数几乎等于重建库。还有一类是数据类型映射问题。比如从Oracle迁移来的number字段到达梦后建议明确映射到精度合适的DECIMAL避免小数位对不上。SQL层面少用Oracle特有、达梦可能不完全兼容的写法例如()外连接在某些场景不如标准ANSI JOIN稳妥。程序里的SQL尽量写成标准风格迁移时能少改一行是一行。注意别小看这些细节迁移项目的工期往往就耗在这些不起眼的兼容性差异上。另外锁等待问题的排查也值得养成固定套路。很多系统卡顿不是数据库性能不好而是两个会话互相等的锁把关键表锁住了。发现锁等待后找到会话对应的SQL和应用模块往往能很快定位到业务逻辑层面的问题比如事务里做了太长的外部调用或者写了事物代码忘了提交。上面这套流程基本覆盖了一个达梦DM8项目从零到能用的完整闭环。我个人在实际操作中最深的体会是达梦虽然叫国产数据库但在使用体验上更像是一个“兼容Oracle并做了大量简化”的变体所以很多老DBA上手会非常顺反而是从MySQL过来的人需要花点时间适应大小写和习惯上的差异。最后再说两个小习惯生产环境改任何参数之前先把dm.ini原文件备份好并在测试实例上验证遇到解释不清的故障优先翻实例目录下的日志大多数答案都写在那里。希望这篇总结能帮你少踩几个坑。后面有时间我再单独写一篇关于达梦主备集群搭建和数据切换演练的实操记录。