ARTICLE DETAIL

资讯详情

深耕编程入门与网站建设的一线实战洞察。

达梦DM8创建用户、表空间与表结构落地实战

达梦DM8创建用户、表空间与表结构落地实战 1. 从一次真实的上手经历说起接手一个国产化改造项目的时候甲方给的服务器上已经装好了达梦数据库 DM8只丢过来一个连接串和一句你自己建库建表吧。当时我第一反应是打开常用的图形化客户端连上去看看结果发现对面这套东西虽然界面长得跟某些主流数据库客户端有几分相似但操作路径、权限模型、表空间的组织方式完全是另一套路子。那天下午我在建用户和建表空间之间反复卡了两个多小时最后才把一条完整链路跑通。这篇内容就是把那次踩坑的全过程摊开来讲。核心围绕三件事在 DM8 下怎么创建一个独立的新用户、怎么给这个用户规划并建立专属表空间、怎么在这套体系下把数据库表结构落地。它解决的是数据库装好了但不知道怎么从零开始规划一套业务库的问题适合刚接触达梦的运维、后端开发以及需要做国产数据库适配的同学参考。不管你是刚开始学达梦数据库使用教程还是已经在做 nacos 适配达梦数据库这类迁移工作这套流程都是绕不开的基本功。有个概念要先摆清楚在很多数据库里库和用户基本是一回事建了用户就等于建了一个逻辑库。DM8 的体系里实例Instance→ 数据库Database→ 表空间Tablespace→ 用户User→ 表Table是一条层级链。一个实例下面通常挂着多个表空间每个用户默认绑定一个同名表空间你在自己的会话里建的表默认就往绑定的那个表空间里落。理解这一点后面的操作逻辑就顺了——我们不是在新建一个数据库而是在一个已经跑起来的实例里划出一块独立地盘给新用户用。下面我按实际操作的顺序走先讲整体规划思路再拆解用户、表空间、表结构这三块的具体做法最后把我遇到过的报错和排查过程整理出来。中间涉及参数的地方我会把为什么这么选讲清楚方便你按自己的环境调整。2. 开工前的整体规划与思路拆解2.1 为什么强烈建议给每个业务建独立用户和表空间很多人上手第一件事是直接用 SYSDBA 这个超级管理员账号建表。能用吗能用。但这是个坏习惯而且在实际生产里会带来三个实打实的麻烦。第一个是权限失控。SYSDBA 拥有实例里的最高权限任何一次误操作都没有兜底一句DROP TABLE敲错对象就直接没了。用普通业务账号你天然被限制在自己 schema 下手滑的伤害半径小得多。第二个是资源隔离。达梦的表空间是可以指定不同数据文件路径的。如果把所有业务都堆在默认的 MAIN 表空间里磁盘涨满了是一起涨满备份恢复也不好按业务切分。单独建表空间之后不同业务的容量可以独立监控、独立做备份策略出问题只影响一个模块。第三个是迁移和审计友好。做国产化替换的时候往往是一个业务一个业务切。一个业务对应一个用户加一套表空间切换和回滚都干净利落不会牵扯到别的模块。我个人的经验是一个中等规模的系统表空间数量控制在 5 到 15 个之间比较舒服。太少了起不到隔离作用太多了管理成本直线上升。具体的划分维度一般按业务模块或者数据冷热来切比如订单、用户、日志各一个表空间日志这种写入量大又不常查的可以单独放一块盘上。2.2 用户、表空间、表结构三者的先后顺序这三样东西的创建顺序不能乱中间的依赖关系是这样的先建表空间表空间是存储数据的物理载体没有它用户的默认数据就没地方放。当然也可以先建用户、用 MAIN 表空间兜着但那样就失去了隔离的意义。再建用户并绑定表空间建用户的时候用DEFAULT TABLESPACE 表空间名指定默认表空间这样这个用户建的所有对象都默认落到里面。最后建表结构用新用户登录在它自己的 schema 下建表、建索引、建约束。顺序反了会怎样如果先建用户、默认表空间用的是 MAIN等你后面想改成新表空间得单独执行ALTER USER ... DEFAULT TABLESPACE ...而且这个改动只对以后新建的对象生效已经建好的表还留在老表空间里。我就在这一步吃过亏——几张表建了一半才想起来换表空间结果变成两处混放后来只能重建。所以宁愿开工前多想五分钟也别中途改。2.3 本次演示的环境与规划表为了讲得具体我给出这次演示用的规划你在自己环境里照着改就行。项目规划值说明实例端口5236DM8 默认端口新用户名APP_USER命名建议大写避免大小写转换麻烦用户默认表空间APP_DATA与业务数据对应表空间数据文件/dm8/data/DAMENG/APP_DATA01.DBF路径按实际安装目录调整初始数据文件大小128M演示用生产按预估容量给表空间自动扩展开启每次 64M避免手动盯容量这套规划里的每个参数我在后面都会讲它的来由。表空间文件的路径有个坑要注意必须放在数据库实例有权限读写的目录下一般是安装目录的 data 子目录随便指到 /root 或者挂载的只读盘上会直接报错。3. 手把手创建新用户与专属表空间3.1 连接数据库的两种方式与选择操作之前得先连上数据库。DM8 常见的入口有两种命令行工具 disql 和图形化客户端。命令行方式在数据库服务器本地最方便安装目录的 bin 下有 disql 可执行文件直接cd /dm8/bin ./disql SYSDBA/SYSDBAlocalhost:5236这里 SYSDBA 的默认密码也是 SYSDBA生产环境第一次登录后必须改掉很多安全扫描直接把这个当高危项报出来。图形化方式就是各类支持达梦的客户端连的时候记住达梦的驱动和协议跟某些数据库不完全一样端口是 5236主机填服务器 IP。我一般习惯建库建用户的活儿用命令行做因为命令可以留成脚本下次照着改参数就能复用日常查数据、看表结构用图形化工具直观。这次的新用户和表空间演示我都用命令行给出来你可以直接复制成 .sql 脚本一次性执行。3.2 创建表空间的完整语句与参数计算建表空间的核心语句是CREATE TABLESPACE最简形式如下CREATE TABLESPACE APP_DATA DATAFILE /dm8/data/DAMENG/APP_DATA01.DBF SIZE 128 AUTOEXTEND ON NEXT 64 MAXSIZE 20480;逐行拆一下这几个参数为什么这么写。DATAFILE后面跟的是数据文件的绝对路径。这个路径必须在数据库服务进程有写权限的目录下通常就是实例的 data 目录。你可以在建库时看到的 dm.ini 里确认实例目录位置。文件名的命名我习惯用表空间名 序号 .DBF将来一个表空间要加第二个数据文件时直接 APP_DATA02.DBF一目了然。SIZE 128表示数据文件初始大小 128MB。这个值别给太小因为文件一旦建好之后再想缩小是很麻烦的。怎么估算我的做法是拿这个业务未来半年到一年的数据量大致估一下再打个对折作为初始大小。比如预计一年 2G初始就给 512M 或者 1G反过来如果只是个小配置表128M 绰绰有余。AUTOEXTEND ON NEXT 64 MAXSIZE 20480是自动扩展策略。开启之后当初始空间用完文件每次自动长 64MB长到 20480MB也就是 20G封顶。为什么要有 MAXSIZE 上限因为一个不加限制的自动扩展文件理论上能把整个磁盘吃满把操作系统拖垮。给个上限等于给自己留了个报警触发点。建完可以查一下确认SELECT TABLESPACE_NAME, STATUS FROM DBA_TABLESPACES WHERE TABLESPACE_NAMEAPP_DATA;STATUS 返回 0 或 NORMAL 之类的正常状态就说明建好了。这里有个细节达梦的表空间状态字段含义跟某些数据库不一样别看到数字就以为出错了以官方文档的状态对照为准。注意数据文件路径如果写成一个不存在的目录DM8 不会自动帮你创建目录会直接报错。建之前用 ls 确认目录存在或者先 mkdir 出来并赋权。3.3 创建用户并绑定默认表空间表空间就位之后建用户CREATE USER APP_USER IDENTIFIED BY App_User#2024 DEFAULT TABLESPACE APP_DATA;这里三个要点。第一密码建议用引号包裹并包含大小写、数字、符号。达梦对密码复杂度有默认校验策略太简单的密码在启用口令策略后会被拒绝。用双引号还有个作用避免大小写被自动转换。第二DEFAULT TABLESPACE APP_DATA指定了默认表空间。这个用户执行CREATE TABLE而不指定表空间时表就落在 APP_DATA 里。第三如果你想同时指定临时表空间排序、临时结果集会用到可以加TEMPORARY TABLESPACE 临时表空间名。一般用默认的 TEMP 就行除非你的业务有大量排序操作需要单独隔离否则不用动。建好用户后这个用户实际上还是空手的——它没有权限做太多事情需要一个基础授权。最小可用的授权组合大致是这样GRANT RESOURCE TO APP_USER; GRANT PUBLIC TO APP_USER; GRANT VTI TO APP_USER; GRANT SOI TO APP_USER;RESOURCE允许创建表、视图、索引等对象这是业务账号最核心的角色。PUBLIC一些公共对象的访问权限不给的话某些查询会异常。VTI访问系统动态视图的权限做监控和排查时有用。SOI允许查询系统对象信息很多客户端连上来会先查这些系统表不授权会出现连上但看不到表的怪现象。授这些角色的时候别一口气把 DBA 也授出去那就失去隔离的意义了。真要临时提权用完记得REVOKE回来。3.4 验证用户与表空间的绑定关系授完权之后先别急着建表用新用户登录进去验一下./disql APP_USER/App_User#2024localhost:5236登录成功后执行SELECT USER, DEFAULT_TABLESPACE FROM USER_USERS;这里能看到当前用户和它绑定的默认表空间。如果DEFAULT_TABLESPACE显示的是你建的那个说明绑定成功。有个常见误区是所有人都以为建用户时写了 DEFAULT TABLESPACE 就一定生效其实如果表空间名写错了达梦在某些版本下不会当场报错而是悄悄回退到默认表空间等你建完表发现位置不对才傻眼。所以我强烈建议建完立刻用这条语句验一遍三十秒的事省掉后面重建的麻烦。4. 数据库表结构设计与落地实操4.1 达梦的数据类型与建表语法要点用户和表空间都就绪了接下来在这一节讲表结构。达梦的建表语法大体兼容 SQL 标准跟很多开发熟悉的写法差异不大但有若干细节要注意。常见数据类型的对应关系大致是整数用INT或BIGINT字符串用VARCHAR(n)定长用CHAR(n)金额或高精度小数用DECIMAL(p,s)或NUMERIC(p,s)日期时间用DATE到天和TIMESTAMP含时分秒以及DATETIME。大文本用CLOB二进制用BLOB。选类型的时候有个通用原则能定长别用变长能小精度别放大精度因为存储和索引效率会明显不同。举个具体的建表示例还是以订单业务为例CREATE TABLE APP_USER.T_ORDER ( ORDER_ID BIGINT NOT NULL, ORDER_NO VARCHAR(32) NOT NULL, USER_ID BIGINT NOT NULL, AMOUNT DECIMAL(18,2) DEFAULT 0, STATUS TINYINT DEFAULT 0, CREATE_TIME TIMESTAMP DEFAULT CURRENT_TIMESTAMP, REMARK VARCHAR(500), CONSTRAINT PK_T_ORDER PRIMARY KEY (ORDER_ID) );几点解释。NOT NULL用在业务上必须非空的字段能加就加数据库层面的约束是最后一道防线别全指望应用层校验。DECIMAL(18,2)给金额18 位总长、2 位小数覆盖绝大多数业务场景比浮点类型安全。DEFAULT CURRENT_TIMESTAMP让创建时间自动填充省得每个 insert 都写一遍。主键用显式的CONSTRAINT PK_T_ORDER PRIMARY KEY命名比匿名约束好将来出问题一眼能定位。如果你是在自己的 schema 下建表可以省略APP_USER.前缀直接CREATE TABLE T_ORDER (...)默认会建在当前用户的默认表空间里。我之所以显式写前缀是为了在脚本里一目了然是哪个 schema 的对象。4.2 索引、注释与约束的补全表建好只是骨架真正让表好用还得补索引和注释。索引这块主键会自动建唯一索引剩下的高频查询字段要手动加CREATE INDEX IDX_ORDER_NO ON APP_USER.T_ORDER(ORDER_NO); CREATE INDEX IDX_ORDER_USER ON APP_USER.T_ORDER(USER_ID, CREATE_TIME);第二条是联合索引为什么把 USER_ID 放前面、CREATE_TIME 放后面这遵循最左前缀原则——查询条件里如果只有 CREATE_TIME这个索引用不上如果只有 USER_ID能用上如果两个都有效果最好。所以联合索引的字段顺序要按区分度高、查询频率高的字段往前放。这是建索引最容易搞反的地方。注释加上方便后来人看懂COMMENT ON TABLE APP_USER.T_ORDER IS 订单主表; COMMENT ON COLUMN APP_USER.T_ORDER.ORDER_NO IS 订单编号业务唯一;外键、唯一约束这些按业务需要加。但我在生产环境里对外键很谨慎因为外键会带来额外的锁开销和插入顺序约束高并发写入场景下容易变成瓶颈。很多团队的做法是逻辑外键在应用层保证数据库层不建物理外键。这个取舍没有绝对对错看你的业务对数据一致性和性能的侧重。4.3 一次性执行的脚本组织方式实际干活时我不会一条条敲而是把上面的内容攒成一个脚本按顺序执行。脚本结构大致如下-- 1. 建表空间 CREATE TABLESPACE APP_DATA DATAFILE /dm8/data/DAMENG/APP_DATA01.DBF SIZE 128 AUTOEXTEND ON NEXT 64 MAXSIZE 20480; -- 2. 建用户 CREATE USER APP_USER IDENTIFIED BY App_User#2024 DEFAULT TABLESPACE APP_DATA; -- 3. 授权 GRANT RESOURCE TO APP_USER; GRANT PUBLIC TO APP_USER; GRANT VTI TO APP_USER; GRANT SOI TO APP_USER; -- 4. 建表此处接建表语句 -- ...为什么要组织成脚本因为下次换环境要重来一遍时改几个参数就能复用而且版本可追溯。用 disql 执行脚本可以用start命令start /path/to/init.sql脚本里我会习惯性在开头加上SET ECHO ON这样每条语句执行时都回显出来出错了能立刻知道卡在哪一句。这个习惯帮我省过很多次排查时间。注意脚本执行到一半失败时前面的语句已经生效了不会自动回滚。所以脚本要么是幂等的加 IF NOT EXISTS 之类的判断要么执行失败后你手动清理已建的对象再重来。达梦的 DDL 语句在部分版本里也是自动提交的别指望它整体事务回滚。5. 常见问题与排查技巧实录5.1 用户与权限相关的典型报错刚上手最常撞的一类错误是权限类报错整理成表方便对照报错关键词可能原因处理方向无效的用户名/密码密码大小写或引号问题确认建用户时是否用双引号包裹权限不足无法创建表用户未授 RESOURCE用 SYSDBA 补 GRANT RESOURCE表或视图不存在用户没授 SOI/VTI补授对应角色后重连无法访问表空间用户默认表空间未正确绑定检查 USER_USERS 视图关于密码达梦默认可能会对密码做大小写不敏感的转换也可能有口令策略要求长度和复杂度。建用户时把密码用双引号包起来是最省心的做法否则像AppUser2024这种混合大小写可能会被静默转成大写登录时你按原样输反而登不进去。这个坑我遇到过不止一次尤其是从别的数据库迁过来的人习惯性不带引号。还有一类是连上了但看不到任何表。这通常是权限问题客户端连上来会先查系统视图用户没有 SOI 权限就一片空白看着像数据库空了其实只是看不到。补权限重连即可。5.2 表空间创建失败的排查路径表空间这块报错相对集中我总结了三条排查路径。第一条路径问题。报错里出现无法创建文件目录不存在之类的字样九成是路径写错了或者权限不够。先确认目录存在再确认数据库服务进程对这个目录有写权限。假设服务是用某个专用账号启动的你用 root 建的目录却没给它权限一样写不进去。ls -ld /dm8/data/DAMENG看一眼属主和权限位必要时chown改属主。这一步在国产化环境里特别常见因为安装脚本和运维手工操作的账号往往不是同一个。第二条重名问题。表空间名和已有表空间重名会直接报错。查一下现有列表SELECT TABLESPACE_NAME FROM DBA_TABLESPACES;第三条容量问题。如果报错提到空间不足检查所在磁盘剩余空间df -h /dm8初始 SIZE 给太大而磁盘不够会直接建失败。这种情况下把 SIZE 调小、加大 MAXSIZE 上限用自动扩展兜着反而更灵活。5.3 从建表到数据导入的衔接问题表结构建完下一步往往是导数据。这一步有个编码相关的坑值得单独说导入数据时经常会遇到本地编码和文件编码不一致的提示比如本地是某个中文字符集、导入文件是另一种编码。这种提示如果处理不好中文会变成乱码。我的处理原则是导入前先确认源文件的实际编码再用工具指定一致的字符集。如果达梦服务端的字符集已经定死建库时确定后期改动非常麻烦那就要让导入文件的编码去凑服务端。中文乱码这个问题在看日志时才发现的成本极高所以导入完成后我会抽查几行中文数据确认显示正常再往下走。另外导入大批量数据前建议先临时关闭或减少日志、约束检查视业务需要导入完再打开并建立索引这样比边导入边建索引快很多。这是导入大表时提速的常规操作。5.4 图形化客户端连接与使用的小技巧命令行之外很多人还是习惯用图形化客户端操作。连达梦时要注意驱动选择端口是 5236别按别的数据库的默认端口填。连接成功后如果只看到很少的 schema多半是权限问题跟我前面说的一样给用户补上系统视图的查询权限。在建表空间这件事上客户端里通常有可视化向导填表空间名、数据文件路径、初始大小、自动扩展参数本质上跟我给的 SQL 语句一一对应。图形化界面适合学习和快速上手但真正要上生产我建议还是把 SQL 脚本留一份因为它可版本化、可 review、可批量执行比界面上点来点去可靠得多。还有个小经验不同版本的客户端和不同版本的 DM8 服务端之间偶尔有兼容性小毛病比如字段显示不全或某些元数据查不出来。遇到这种玄学问题先换命令行验证一下能确认是客户端的问题还是数据库的问题别一上来就怀疑自己 SQL 写错了。6. 一些实操中攒下来的个人经验整套流程走下来真正容易出问题的从来不是 SQL 语法本身而是环境和权限这些外围的东西。我最大的体会是建库建表这件事七分规划、三分执行。开工前把表空间切分、用户命名、字符集、数据文件路径想清楚后面执行十分钟就能搞定反过来图省事几个概念都堆在默认配置上等出了乱码或者空间爆掉回头整理的代价要大得多。另一个反复验证有效的做法是所有 DDL 操作都留脚本并且在自己本地的测试实例上先跑一遍。达梦的语法虽然跟主流数据库高度接近但在默认值、约束命名、临时表、自增列这些细节上还是有差异的。比如自增列的实现方式、字符串函数的行为跟其他数据库对不上的地方不少先跑一遍再上生产能避开大量临场救火。最后留一个我认为值得养成的小习惯每次建完用户和表空间顺手记录一份环境清单——用户名、表空间名、数据文件路径、初始大小、字符集。这份清单在你做备份恢复、迁移或者排查问题时价值远超你记录它的那两分钟。等哪天需要把一个业务整套搬到另一台机器上这份清单直接就是你的迁移文档。
返回列表