尧图网站设计 尧图网站设计YAOTU DESIGN
ARTICLE DETAIL

资讯详情

深耕网站设计与一线实操的经验洞察。

达梦 DM8 建库全链路:表空间、用户、模式与导入导出避坑

达梦 DM8 建库全链路:表空间、用户、模式与导入导出避坑 上周帮一个做信创改造的团队看环境开发跑过来说建表一直报错我登上去一看用户是建了但默认表空间还挂在 MAIN 上索引和数据文件全挤在一个 128M 的文件里扩容也没做规划。这种情况我遇到过太多次了问题不出在 SQL 语法上而是建库之初没把用户、表空间、模式这三件事当成一个整体来设计。达梦 DM8 在这块跟很多人熟悉的 MySQL 差别不小MySQL 里CREATE DATABASE一把梭的思维搬到达梦上会连着踩坑。这篇内容我打算把 DM8 从实例初始化、表空间规划、建用户、建表结构到数据导入导出这一整条链路讲透重点放在那些官方文档里一笔带过、但实际部署时天天要面对的参数和细节比如页大小、字符集、大小写敏感这几个一次定终身的设置还有 dexp/dimp 导入时那个把人折腾得够呛的 PG_GBK 与 PG_UTF8 编码问题。适合刚开始接触达梦的运维和开发也适合从 Oracle 迁移过来、想知道两者差异的老手参考。1. 建用户这件事为什么在DM8里要先谈表空间和模式1.1 新手的典型翻车路径大部分人的操作顺序是这样的装完数据库用 SYSDBA 登进去直接敲一句CREATE USER APP IDENTIFIED BY App12345;然后GRANT DBA TO APP;觉得搞定了。接着用 APP 登录建表发现表建到了 MAIN 表空间里跑了几天业务量上来MAIN 表空间告警再回头想把表挪走就得挨个ALTER TABLE ... MOVE TABLESPACE ...中间还要处理索引失效、约束重建的问题。这个坑的根源在于 DM8 的默认行为CREATE USER如果不显式指定DEFAULT TABLESPACE用户对象会落到实例初始化时设定的默认表空间通常是 MAIN。而 MAIN 表空间在 dminit 初始化时只给了 128M虽然开了自动扩展但默认的扩展上限往往也不够生产环境用。第二个容易忽略的点是模式。DM8 里用户和模式是强绑定的关系执行CREATE USER的同时系统会自动创建一个与用户名同名的模式。这一点和 Oracle 一致但和 MySQL 的库概念完全不同。很多从 MySQL 转过来的人会习惯性再执行一次CREATE SCHEMA APP结果直接报模式已存在。更麻烦的是如果业务代码里的 SQL 硬编码了APP.T_ORDER这种带模式前缀的写法后面想改用户名就等于要改一遍代码。我的建议是用户名的命名规则在项目启动阶段就固定下来一旦确定就不要动。名字本身用什么无所谓APP_BIZ、BIZ_USER都行但得统一比如按业务域划分一个业务域一个用户不要一个库塞十几种业务。1.2 DM8自带的四个表空间各自干什么初始化一个全新实例之后DM8 会自动创建几个系统表空间这块必须搞清楚不然后面排查空间问题会一头雾水。表空间名用途能否删除备注SYSTEM存放数据字典、系统表和系统视图否空间不足会直接导致库不可用ROLL存放回滚记录否大事务会撑爆它需要重点监控TEMP临时表空间排序、哈希连接用否复杂查询多的话要加大MAIN默认用户表空间理论可删但不建议大小默认 128MHMAINHUGE 表列存专用可用不到列存可以不关注实际项目里我一般这么分配系统相关的全部保持默认业务数据建独立的表空间索引再单独建一个如果有列存分析需求HMAIN 单独扩容。为什么要数据文件和索引文件分开两个原因一是随机 IO 和顺序 IO 的访问模式不同分开放在不同物理盘上能减少争抢二是某张表数据损坏需要恢复时索引可以重建不用一起恢复省时间。顺便说说热词里提到的 DW 和 DSC 的区别因为这直接影响到表空间的规划思路。DSC达梦共享存储集群是多个实例挂同一份共享存储上的数据文件类似 Oracle RAC这时候表空间的每个数据文件都必须放在共享存储上且所有节点看到的路径要一致。而 DW数据守护是一主多备主库写、备库重做日志硬件和数据文件都是独立的表空间规划按单机来就行。这两者在建表空间时的差别DSC 要额外注意数据文件必须落在共享盘、不能加本地盘路径DW 则要留意主备两边的目录结构保持一致否则切换后 dm.ini 里的路径对不上。2. 实例初始化dminit阶段就要定死的参数2.1 一次定终身的四个参数DM8 的PAGE_SIZE、EXTENT_SIZE、CHARSET、LENGTH_IN_CHAR、CASE_SENSITIVE、BLANK_PAD_MODE这几个参数一旦初始化完成就不能修改只能删库重建。这不是危言耸听我见过为了改字符集把整个库导出再重建的案例前后折腾了两天。先说PAGE_SIZE数据页大小可选 4K、8K、16K、32K。OLTP 场景建议 16KOLAP 场景建议 32K。为什么页越大单次 IO 读的数据越多对大表扫描、统计分析有利但页越大小事务写入时的写放大也越明显OLTP 场景下 32K 的页会浪费不少空间。达梦官方文档里说初次使用建议 32K但我个人的实践是如果业务系统事务量大、单行数据小16K 更划算。CHARSET只有 0GB18030和 1UTF-8两个常用选项。2024 年了除非你有明确的国标对接需求否则一律选 UTF-8。这个后面导入导出那节会重点展开。LENGTH_IN_CHAR这个参数特别容易被忽略但它的影响面极大。取值 1 时VARCHAR(10)表示 10 个字符取值 0 时表示 10 个字节。UTF-8 下一个汉字占 3 个字节也就是说如果设成 0VARCHAR(10)只能存 3 个汉字第 4 个就报截断错误。更坑的是如果建表时没有意识到这一点后期想改就意味着所有涉及长度的字段类型都要重新评估。CASE_SENSITIVE建议保持 1大小写敏感。虽然设成 0 会让迁移时更省事但达梦很多系统视图、系统函数的名字是区分大小写的设成 0 有时反而会引发一些难以定位的问题。参数速查表参数可选值推荐值能否修改PAGE_SIZE4/8/16/32OLTP 16OLAP 32否EXTENT_SIZE16/32页16否CHARSET0GB180301UTF-81否LENGTH_IN_CHAR0/11否CASE_SENSITIVE0/11否BLANK_PAD_MODE0/11兼容 Oracle否BLANK_PAD_MODE这个参数值得一提它控制字符串比较和存储时是否对尾部空格做填充处理。从 Oracle 迁移过来的项目建议设 1行为更接近否则abc和abc 的比较结果会和原来不一样这种差异在业务代码里排查起来非常痛苦。2.2 一份可直接复制的初始化命令与目录规划假设你已经在 Linux 上装好了 DM8安装路径是/opt/dmdbms接下来做实例初始化。先规划目录我的习惯是按实例名分目录mkdir -p /dmdata/DAMENG chown -R dmdba:dinstall /dmdata然后切到 dmdba 用户执行 dminitcd /opt/dmdbms/bin ./dminit PATH/dmdata DB_NAMEDAMENG \ INSTANCE_NAMEDMSERVER \ PORT_NUM5236 \ PAGE_SIZE16 \ EXTENT_SIZE16 \ CHARSET1 \ LENGTH_IN_CHAR1 \ CASE_SENSITIVE1 \ BLANK_PAD_MODE1 \ SYSDBA_PWDDmSysdba2024 \ SYSAUDITOR_PWDDmAuditor2024PATH是数据文件存放的根目录DB_NAME是数据库名会和实例名一起决定数据目录结构。执行完之后会在/dmdata/DAMENG下生成 dm.ini、数据文件、控制文件等。2.3 服务注册与开机自启初始化完成后数据目录里还没有服务。手动启动的话可以./dmserver /dmdata/DAMENG/dm.ini但生产环境肯定要用服务方式。达梦提供了注册脚本./dm_service_installer.sh -t dmserver -dm_ini /dmdata/DAMENG/dm.ini -p DMSERVER执行完会在/etc/systemd/system下生成DmServiceDMSERVER.service。之后就可以用systemctl start DmServiceDMSERVER启动了。注意这个脚本要用 root 执行或者有 sudo 权限。注册完之后记得systemctl enable DmServiceDMSERVER设置开机自启。这里有个小经验如果服务器上跑多个达梦实例服务名的-p后缀一定要区分开比如-p BIZ01、-p BIZ02否则会互相覆盖。还有就是如果后面修改了 dm.ini 里的端口要重启服务才生效光 reload 不行。3. 表空间的规划与创建3.1 CREATE TABLESPACE语句逐字段拆解实例起来之后用 disql 连上去./disql SYSDBA/DmSysdba2024localhost:5236然后建业务表空间。我先给一份完整语句再逐字段解释CREATE TABLESPACE TBS_BIZ DATAFILE TBS_BIZ01.DBF SIZE 2048 AUTOEXTEND ON NEXT 256 MAXSIZE 20480;DATAFILE后面给的是文件名如果不带路径会默认创建在数据目录下也就是/dmdata/DAMENG/。建议不带路径让达梦自己管这样迁移的时候路径不会出错。如果非要指定绝对路径注意 DM8 要求该路径必须提前存在且属于 dmdba 用户。SIZE单位是 MB这里给 2048M。关于初始大小怎么定我的经验是初始大小给到预期一年数据量的 30% 到 50%剩下的靠自动扩展。给太小会频繁扩展每次扩展都涉及文件系统操作有性能开销给太大又会浪费存储。AUTOEXTEND ON NEXT 256表示每次扩展 256M。这个值不要太大会比较安全。MAXSIZE 20480是上限 20G。这里我强烈建议一定要设 MAXSIZE不要图省事用UNLIMITED。原因很现实磁盘写满导致数据库挂掉比表空间满了导致写入失败要严重得多。表空间满了你可以扩容、可以告警、可以处理磁盘满了整个实例可能直接崩恢复起来麻烦得多。索引表空间同理再建一个CREATE TABLESPACE TBS_BIZ_IDX DATAFILE TBS_BIZ_IDX01.DBF SIZE 1024 AUTOEXTEND ON NEXT 128 MAXSIZE 10240;3.2 扩容的三种做法表空间满了怎么办DM8 提供了三种路径各有各的适用场景。第一种给现有的数据文件加自动扩展或者调大上限ALTER TABLESPACE TBS_BIZ DATAFILE TBS_BIZ01.DBF AUTOEXTEND ON NEXT 256 MAXSIZE 40960;这种做法最简单业务无感知但单个数据文件在部分文件系统上有大小限制比如 ext4 单文件上限很大但有些老文件系统有 2G 限制而且单个文件过大对备份和恢复的时间有影响。第二种新增数据文件ALTER TABLESPACE TBS_BIZ ADD DATAFILE TBS_BIZ02.DBF SIZE 4096 AUTOEXTEND ON NEXT 256 MAXSIZE 40960;这是我最推荐的方式。数据分散在多个文件里单个文件控制在一定大小内IO 也能分散到不同文件。而且 DM8 在表空间内的数据文件之间会自动做均衡新写入的数据会优先往剩余空间多的文件放。第三种直接调整已有数据文件的大小ALTER TABLESPACE TBS_BIZ RESIZE DATAFILE TBS_BIZ01.DBF TO 8192;这个只能调大不能调小到当前已用空间以下。一般用在预先知道要批量导入大量数据、不想等自动扩展一点点涨的场景。注意任何表空间的扩容操作都要先确认操作系统层面的磁盘剩余空间别表空间设了 40G 上限磁盘只剩 5G那就等着出事。3.3 巡检SQL和状态管理日常巡检我常用的几条-- 查所有表空间基本信息 SELECT NAME, TYPE$, STATUS$, TOTAL_SIZE, FREE_SIZE FROM V$TABLESPACE; -- 查数据文件和大小 SELECT TABLESPACE_NAME, FILE_NAME, BYTES/1024/1024 AS MB, AUTO_EXTENSIBLE, MAXBYTES/1024/1024 AS MAX_MB FROM DBA_DATA_FILES; -- 按表空间汇总使用率 SELECT TABLESPACE_NAME, SUM(BYTES)/1024/1024 AS TOTAL_MB FROM DBA_DATA_FILES GROUP BY TABLESPACE_NAME;V$TABLESPACE里的TOTAL_SIZE和FREE_SIZE单位大多是页换算成 MB 要除以 1024 再乘以 PAGE_SIZE/1024这点第一次看容易算错我见过有人把页数当成 MB 数吓了一跳以为表空间快爆了。表空间还有状态管理。正常情况下是 ONLINE。做维护的时候可以把表空间置为 OFFLINEALTER TABLESPACE TBS_BIZ OFFLINE; -- 维护完再拉起来 ALTER TABLESPACE TBS_BIZ ONLINE;但要注意SYSTEM、ROLL、TEMP 这几个系统表空间不能 OFFLINE只有用户表空间可以。OFFLINE 状态下该表空间里的表无法访问业务会报错所以这个操作一般只在实际停机维护窗口里做。4. 创建用户与模式绑定4.1 用户、模式、表空间的关系先把概念理清楚这三者的关系是很多人混淆的起点。在 DM8 里用户是登录身份模式是对象的命名空间表空间是物理存储的容器。一个用户默认拥有一个同名模式用户创建的所有对象表、视图、索引默认放在这个模式下。多个用户可以通过授权访问同一个模式下的对象但一个模式只能属于一个用户除了系统模式。用 MySQL 的思维理解就是MySQL 的库约等于达梦的模式MySQL 的用户是纯粹的账号和权限集合。所以从 MySQL 迁移时不要试图把库直接对应成用户正确的是把库对应成模式然后单独建一个用户去管它。还有一个经常被问的问题CREATE USER和CREATE SCHEMA到底什么关系答案是CREATE USER会自动建一个同名模式你不需要再手动建。如果你确实需要给一个用户建第二个模式可以用CREATE SCHEMA BIZ_ARCHIVE AUTHORIZATION APPUSER;这条语句必须在 SYSDBA 下执行意思是创建一个属于 APPUSER 用户的模式 BIZ_ARCHIVE。执行完之后 APPUSER 就有了两个模式。这种用法在数据归档场景下比较常见活跃数据和历史数据用不同模式分开。4.2 一条完整的建用户语句CREATE USER APPUSER IDENTIFIED BY AppUser2024 DEFAULT TABLESPACE TBS_BIZ DEFAULT INDEX TABLESPACE TBS_BIZ_IDX ACCOUNT UNLOCK;密码这里有个坑DM8 默认有一条密码策略要求密码长度、包含大小写字母、数字、特殊字符等。具体策略由PWD_POLICY参数控制取值是各位的组合1 禁止与用户名相同2 检查密码长度4 至少包含一个大写字母8 至少包含一个数字……。如果建用户时报密码不符合策略要求别急着重启改参数先去查一下SELECT * FROM V$DM_INI WHERE PARA_NAME PWD_POLICY;生产环境我不建议把策略关掉反而应该往上加。密码复杂度是最后一道防线尤其是数据库这种能直接导出全量数据的系统。如果实在需要临时放宽比如给某个只读账号设个简单密码做演示可以调整到最低要求但演示完记得改回来。DEFAULT INDEX TABLESPACE这个子句在不同版本的 DM8 上支持情况不太一样如果提示语法错误就去掉它在建索引时显式指定表空间CREATE INDEX IDX_ORDER_NO ON APPUSER.T_ORDER(ORDER_NO) TABLESPACE TBS_BIZ_IDX;4.3 授权到底给到什么程度建完用户接下来是授权。DM8 内置了几个角色角色名权限范围适用场景DBA几乎全部权限不能审计库管理员RESOURCE建表、建视图、建索引、建存储过程业务开发账号PUBLIC基本的查询权限所有用户默认拥有SOI系统视图相关权限运维查询VTI系统动态视图权限监控账号业务账号我一般给 RESOURCE 加 PUBLIC不给 DBAGRANT RESOURCE, PUBLIC TO APPUSER;为什么不给 DBA因为 DBA 角色能建用户、能删表空间、能操作其他模式的表。业务程序如果被注入或者有 bug误删别人数据的风险是实实在在的。权限最小化这个原则平时感觉不到好处出事的时候能救命。如果是给监控平台用的只读账号那就要更细CREATE USER MONITOR IDENTIFIED BY Mon2024 DEFAULT TABLESPACE TBS_BIZ; GRANT PUBLIC TO MONITOR; GRANT SELECT ON APPUSER.T_ORDER TO MONITOR; GRANT SELECT ON APPUSER.T_USER TO MONITOR;再配合SELECT ANY TABLE之类的系统权限具体看监控需要读多少表。还有一种做法是给 VTI 角色能查动态视图做性能监控足够用。4.4 锁定、解锁、改密、删除这几个操作在运维里出现频率很高一并说了。-- 查看用户状态 SELECT USERNAME, ACCOUNT_STATUS, DEFAULT_TABLESPACE, CREATED FROM DBA_USERS; -- 锁定离职、异常账号 ALTER USER APPUSER ACCOUNT LOCK; -- 解锁 ALTER USER APPUSER ACCOUNT UNLOCK; -- 改密码 ALTER USER APPUSER IDENTIFIED BY NewPwd2024; -- 强制下次登录改密 ALTER USER APPUSER PASSWORD EXPIRE; -- 调整表空间配额 ALTER USER APPUSER QUOTA UNLIMITED ON TBS_BIZ; ALTER USER APPUSER QUOTA 5120 ON TBS_BIZ; -- 删除用户谨慎 DROP USER APPUSER CASCADE;QUOTA这个功能值得单独说。它限制的是用户在某个表空间上能使用的空间上限。默认情况下用户建对象是受表空间总大小限制的不额外限制配额。在多租户共享表空间的场景下给每个用户设配额能防止一个业务把表空间吃光、其他业务没法写入的情况。DROP USER ... CASCADE会连同该用户模式下的所有对象一起删掉这个操作没有回收站删了就没了。我有个习惯执行之前先确认没有别的用户在用它的对象SELECT GRANTEE, TABLE_NAME FROM DBA_TAB_PRIVS WHERE OWNER APPUSER;再检查有没有外键依赖其他模式的表。这些确认动作加起来不到一分钟但能避免很多麻烦。5. 表结构落地类型、约束与大小写5.1 字段类型选择和几个容易搞错的点DM8 的数据类型基本向 Oracle 靠拢从 MySQL 迁过来的人需要重新建立映射关系。几个关键对照MySQL 类型DM8 对应注意点INTINT / INTEGER一致BIGINTBIGINT一致TINYINTTINYINT达梦的 TINYINT 有符号范围 -128~127VARCHAR(n)VARCHAR(n)受 LENGTH_IN_CHAR 影响TEXTCLOB / TEXTTEXT 在 DM8 里底层还是 CLOBDATETIMEDATETIME / TIMESTAMPDM8 的 DATETIME 精度到毫秒DECIMAL(m,n)DECIMAL(m,n)一致BLOBBLOB一致VARCHAR和VARCHAR2在 DM8 里都支持行为一致VARCHAR2是从 Oracle 带过来的习惯写法。我建议统一用VARCHAR语义上更通用。关于长度前面强调过LENGTH_IN_CHAR1时长度单位是字符。但要注意即使设成 1字段的字节上限依然存在比如VARCHAR(8188)在 32K 页大小下的最大长度。一般情况下 VARCHAR 总长不建议超过 4000 字符太长了管理起来麻烦大字段应该用 CLOB。还有一个非常容易踩的坑DM8 里字符串类型的空串和 NULL 是等价的。INSERT INTO t VALUES()实际上插入的是 NULLSELECT出来的也是 NULL。这一点和 Oracle 一致但和 MySQL 不一致MySQL 里空串和 NULL 是两回事。如果业务代码里有用空串判断的逻辑迁移时要重点检查。5.2 一份带注释和约束的完整建表脚本用 APPUSER 登录建一张订单表作为示例CREATE TABLE APPUSER.T_ORDER ( ID BIGINT NOT NULL, ORDER_NO VARCHAR(32) NOT NULL, USER_ID BIGINT NOT NULL, AMOUNT DECIMAL(18,2) DEFAULT 0.00 NOT NULL, STATUS TINYINT DEFAULT 0 NOT NULL, REMARK VARCHAR(500), CREATE_TIME TIMESTAMP DEFAULT SYSDATE NOT NULL, UPDATE_TIME TIMESTAMP DEFAULT SYSDATE NOT NULL, CONSTRAINT PK_T_ORDER PRIMARY KEY (ID) USING INDEX TABLESPACE TBS_BIZ_IDX, CONSTRAINT UK_T_ORDER_NO UNIQUE (ORDER_NO) USING INDEX TABLESPACE TBS_BIZ_IDX ); COMMENT ON TABLE APPUSER.T_ORDER IS 订单主表; COMMENT ON COLUMN APPUSER.T_ORDER.ID IS 主键ID雪花算法生成; COMMENT ON COLUMN APPUSER.T_ORDER.ORDER_NO IS 订单号业务唯一; COMMENT ON COLUMN APPUSER.T_ORDER.USER_ID IS 下单用户ID; COMMENT ON COLUMN APPUSER.T_ORDER.AMOUNT IS 订单金额单位元; COMMENT ON COLUMN APPUSER.T_ORDER.STATUS IS 状态0待支付 1已支付 2已完成 3已取消; COMMENT ON COLUMN APPUSER.T_ORDER.CREATE_TIME IS 创建时间; COMMENT ON COLUMN APPUSER.T_ORDER.UPDATE_TIME IS 更新时间; CREATE INDEX IDX_T_ORDER_USER ON APPUSER.T_ORDER(USER_ID) TABLESPACE TBS_BIZ_IDX; CREATE INDEX IDX_T_ORDER_CTIME ON APPUSER.T_ORDER(CREATE_TIME) TABLESPACE TBS_BIZ_IDX;这里有几个细节值得说明。第一建表时显式带上模式名APPUSER.T_ORDER即使当前登录用户就是 APPUSER。这样做的目的是让脚本的语义明确别人看 DDL 一眼就知道表属于谁。第二主键和唯一约束用USING INDEX TABLESPACE指定索引表空间这样才真正做到了索引和数据分离。第三时间类字段给了DEFAULT SYSDATE但业务系统里我更建议由应用层控制时间数据库的默认值只作为兜底原因是应用层的时间更容易统一时区和精度策略。SYSDATE在 DM8 里返回的是数据库服务器时间精度到秒。需要毫秒精度的用SYSTIMESTAMP。5.3 索引表空间分离与主键选择主键用什么类型这个在达梦上讨论得比 MySQL 少但同样重要。自增主键在 DM8 里支持IDENTITY(1,1)ID BIGINT IDENTITY(1,1) NOT NULL这个写法简单但会带来一个问题插入时必须让数据库生成主键应用层拿不到预生成的值除非用SELECT IDENTITY之类的函数。在分库分表或者需要提前知道主键的场景下我倾向用应用层生成比如雪花算法字段就写成普通 BIGINT。关于索引DM8 的索引类型主要是 B 树索引默认就是 B 树。还有位图索引BITMAP适合低基数列比如状态字段但位图索引在并发写入时会锁住整个位图段OLTP 场景慎用。函数索引在 DM8 里也支持CREATE INDEX IDX_T_ORDER_MONTH ON APPUSER.T_ORDER(SUBSTR(ORDER_NO, 1, 6)) TABLESPACE TBS_BIZ_IDX;顺带提一句热词里出现的生成首拼码函数。达梦没有内置的拼音首字母转换函数需要自己写。常见的做法是建一张汉字到首字母的映射表然后写一个 PL/SQL 函数逐字查表拼接。数据量不大的话也可以把映射关系直接写进函数的 CASE 分支里。这种函数在客户名称、商品名称的模糊检索场景下很有用比如输入zlyy能匹配到中联医药。要注意的是映射表方案在字符集为 GBK 时需要按字节处理UTF-8 下按字符处理两者的实现逻辑完全不同写之前先确认库的字符集。6. 客户端接入disql、管理工具和第三方工具6.1 disql与DM管理工具原生工具是最省事的。disql 是命令行客户端在/opt/dmdbms/bin下./disql APPUSER/AppUser2024localhost:5236登录进去之后\l列出所有模式\d描述当前模式的表\c切换连接。脚本执行用./disql APPUSER/AppUser2024localhost:5236 -f /tmp/init.sqlDM管理工具Manager是图形化的类似 PL/SQL Developer 的定位功能挺全建表、执行 SQL、看执行计划、导出 DDL 都能做。这个工具在安装目录的/opt/dmdbms/tool下需要在有图形界面的环境下运行远程用的话得配 X11 转发或者 VNC。现在达梦也出了 Web 版的工具部署在服务端浏览器直接访问比 X11 转发方便。6.2 第三方客户端的配置要点与报错排查很多人习惯用 Navicat 或者 DataGrip 连达梦这块有几个容易卡住的点。用 Navicat 连接 DM8需要选对连接类型。新版 Navicat Premium 已经内置了达梦的驱动选项选达梦或者DM即可端口默认 5236主机填服务器地址。如果 Navicat 版本比较老找不到达梦连接类型那就比较麻烦了因为它不支持像 MySQL 那样自己加载任意 JDBC 驱动。用 DataGrip 或者 DBeaver 这类支持自定义驱动的工具配置就灵活多了。驱动类名dm.jdbc.driver.DmDriverJDBC URL 格式jdbc:dm://192.168.1.100:5236 jdbc:dm://192.168.1.100:5236/APPUSER第二个写法带了模式名连接后默认在 APPUSER 模式下。需要指定字符集的话加参数jdbc:dm://192.168.1.100:5236?characterEncodingUTF-8驱动 JAR 包在/opt/dmdbms/drivers/jdbc/DmJdbcDriver18.jar注意要选和 JDK 版本匹配的JDK 8 用DmJdbcDriver18.jar这个名字有点误导看名字是 18 但实际支持 JDK 1.8具体版本对应关系看驱动目录下的说明文件。常见的连接失败原因我按出现频率排一下报错信息大概率原因处理方式连接超时防火墙没开 5236 端口检查 firewalld 或 iptables用户名或密码错误大小写、密码策略用 disql 本地验证一次网络通信异常客户端和服务端版本不匹配换用和服务端同版本的驱动中文乱码JDBC URL 少了字符集参数加上 characterEncodingUTF-8找不到驱动类JAR 包没加载或版本不对重新指定驱动文件路径顺带说说 Nacos 适配达梦的场景这两年问的人挺多。Nacos 从 2.2 版本开始支持多数据源要让它用达梦做配置存储需要把达梦的 JDBC 驱动包放进 Nacos 的 plugins 目录然后在 application.properties 里改数据源配置把spring.datasource.platform设成dm并配置对应的驱动类名和 URL。坑在于 Nacos 的建表脚本默认只有 MySQL 版本达梦需要自己改 DDL注意把AUTO_INCREMENT换成IDENTITYENGINEInnoDB这些 MySQL 专有语法全部删掉。7. 导入导出、备份与几个上线后才暴露的坑7.1 dexp/dimp的编码参数这是我在达梦上踩得最深的坑没有之一。用 dexp 导出的 dmp 文件换一台服务器用 dimp 导入中文全是乱码或者直接报编码错误。事情的本质是这样的dexp/dimp 的ENCODING参数控制的是 dmp 文件本身的编码它和数据库实例的字符集是两个独立的东西。默认情况下导出的 dmp 文件编码跟随数据库字符集。但如果导出和导入的两端字符集不一致就必须显式指定。导出时./dexp USERIDAPPUSER/AppUser2024localhost:5236 \ FILE/tmp/app.dmp \ LOG/tmp/app_exp.log \ SCHEMASAPPUSER \ ENCODINGUTF-8导入时./dimp USERIDAPPUSER/AppUser2024localhost:5236 \ FILE/tmp/app.dmp \ LOG/tmp/app_imp.log \ ENCODINGUTF-8热词里提到的PG_GBK和PG_UTF8是编码参数的另一种写法带 PG_ 前缀两种写法达梦都认。遇到导入时本地编码:PG_GBK, 导入文件编码:PG_UTF8这种提示说明 dmp 里记录的文件编码和当前实例的本地编码不匹配。处理办法分两种情况。如果只是编码标记不一致但内容没问题加参数忽略检查./dimp ... ENCODINGUTF-8 IGNORE_INIT_ERROR1或者用NOLOG之类的参数先试导。但如果内容真的乱码了那就得先把源库的数据以正确编码重新导出一次。我的做法是导出前先确认两边字符集SELECT UNICODE();返回 0 是 GB180301 是 UTF-8。两侧不一致的话在导出时就把 dmp 转成目标库的编码而不是导入时硬转成功的概率高很多。还有一点跨平台迁移时注意文件名大小写和路径分隔符。Linux 和 Windows 的数据文件路径写法不同如果 dmp 里记录了绝对路径导入到不同目录结构的机器上会失败用REMAP_SCHEMA和REMAP_TABLESPACE参数重映射./dimp ... REMAP_SCHEMAOLD_USER:NEW_USER REMAP_TABLESPACETBS_OLD:TBS_NEW7.2 物理备份和逻辑备份的分工达梦的备份分两套体系。物理备份用 dmrman备份的是数据文件、控制文件的二进制副本速度最快适合全库级别的完整保护。执行前需要确保 DmAPService 服务是启动的这是达梦的辅助进程服务负责备份相关的底层操作否则会报错。一个基础的完全备份./dmrman CTLSTMTBACKUP DATABASE /dmdata/DAMENG/dm.ini FULL TO BACKUP_FILE1 BACKUPSET /dmbackup/full_20240101物理备份的恢复要在停机状态下做恢复过程涉及RESTORE和RECOVER两个阶段还需要配合归档日志才能恢复到最新状态。所以生产环境一定要开归档ALTER DATABASE MOUNT; ALTER DATABASE ARCHIVELOG; ALTER DATABASE ADD ARCHIVELOG DEST/dmarch, TYPELOCAL, FILE_SIZE1024, SPACE_LIMIT102400; ALTER DATABASE OPEN;逻辑备份就是我前面说的 dexp/dimp导出的是 SQL 层面的对象和数据。它的优点是跨版本、跨平台兼容性好能选择性导出按模式、按表缺点是慢大数据量下不太实用。我的实践是日常全量用物理备份版本升级、数据迁移、按表恢复用逻辑备份两者配合别指望一个能覆盖所有场景。7.3 实测踩过的坑最后说几个实际部署中遇到、但文档里不太提的问题。第一个表空间创建之后数据文件没有立刻落盘。这是正常的达梦用的是稀疏文件thin provisioningSIZE 给了 2G 不代表磁盘上立刻占用 2G。用du -sh看和ls -l看的大小会差很多别以为文件没建成功。想确认实际占用du -sh更准。第二个ALTER USER ... QUOTA对已有数据不生效校验。也就是说如果你先建了 5G 数据再设配额 2G这条语句不会报错但后续写入会被拒绝。配额检查只在写入时做不做历史数据的回溯校验这点要清楚。第三个索引表空间没设好重建索引时会报错。特别是用了USING INDEX TABLESPACE的约束索引如果那个表空间被 OFFLINE 了对表的写入会直接失败报索引不可用。所以索引表空间的可用性直接关系到业务写入监控不能漏。第四个LENGTH_IN_CHAR与现有数据迁移的冲突。从 MySQL 或者 Oracle 迁过来的表如果原库的 VARCHAR 长度是按字节算的迁到达梦后长度语义可能变了。我在一个项目里遇到过原库VARCHAR(60)存了 20 个汉字UTF-8 下 60 字节迁到达梦后 LENGTH_IN_CHAR160 变成了 60 个字符看起来更宽松了没问题但如果反过来达梦的VARCHAR(60)迁移到字节语义的库就会截断。迁移前一定要做长度语义的对照测试挑几个存了最长内容的字段实际跑一遍。第五个用户删除时的依赖检查。前面提过要查DBA_TAB_PRIVS但还有一个更隐蔽的视图、存储过程、触发器里可能引用了这个用户的对象。这些依赖藏在DBA_DEPENDENCIES里SELECT OWNER, NAME, TYPE, REFERENCED_OWNER, REFERENCED_NAME FROM DBA_DEPENDENCIES WHERE REFERENCED_OWNER APPUSER;我有个习惯删用户之前先把这条查询跑一遍把结果贴到变更单里作为附件。这样做一方面是为了安全另一方面是万一真出问题了事后能回溯到底删了什么。我个人在实际操作中的体会是达梦 DM8 的这套体系其实并不复杂用户、模式、表空间三个概念理清之后剩下的都是熟练度问题。真正容易出事的不是语法写错而是规划缺失——表空间不设上限、字符集初始化时随手指一个、权限图省事全给 DBA。这些决定在项目初期花不了半小时但能省掉后期几天的返工。所以每次新建环境我都会先花点时间把这几张表列出来实例参数怎么定、分几个表空间、每个多大、上限多少、几个用户、各给什么权限。列清楚了再动手敲命令比边建边想靠谱得多。
返回列表