目录 搜索

达梦命令行交付实操:登录、表空间、授权与建表 · 交互版

一次交付里最小的一套动作 —— 能登录、有地方存、有人能用、能建出表。五步走完,每一条命令后面都跟着真实执行输出;本文只讲 disql,不出现任何图形工具操作。

集群实例实测 DM8 2026-08-03(DPC 四节点) 授权口径已实测核实 5 步全程可复制
disql CREATE TABLESPACE CREATE USER GRANT RESOURCE / SOI / VTI CREATE TABLE
先说一处与常见说法不一致的地方。现场流传的授权口径是「给 VTI / SOI / RESOURCE」。 本篇按这套口径授完权限后逐项去查,结果是:RESOURCE 在建对象、SOI 在让元数据查得到、而 VTI 在本版本是个空角色 (系统权限 0 条、对象权限 0 条、嵌套角色 0 个)。第 4 步有撤/授对照实验,你可以自己复跑。
这不是要推翻现场口径 —— 授 VTI 不会出错,也不会挡住任何事,只是它不提供任何权限,别指望它解决「看不到视图」的问题。

五步概览:每一步的产出和最容易错的地方

照着顺序做,每步结尾会告诉你「怎么证明这步真的成了」。
步骤 这条命令产出什么 怎么证明它成了 最容易错的地方
1 · 登录
disql
一个能执行 SQL 的会话 回显 mode is normal, state is open 口令含 # 会被当成扩展选项;口令错时不会退出,而是掉回交互输入
2 · 表空间
CREATE TABLESPACE
一个带数据文件的命名存储区 dba_data_files 里有这一行 在集群里,文件不一定落在你连的那个节点上;DDL 成功时什么都不打印
3 · 用户
CREATE USER
一个能登录的账号,带默认表空间 dba_users 的 DEFAULT_TABLESPACE 只写在建用户语句里不算数,必须回查这一列
4 · 授权
GRANT
建对象 + 查元数据的权限 dba_role_privs 里有这三行 以为授了就什么都能查;VTI 在本版本是空角色
5 · 建表
CREATE TABLE
一张真能在里面存数据的表 user_tables 的 TABLESPACE_NAME 建表成功 ≠ 落在你要的表空间,必须查 user_tables
一句话记住:这套动作里真正会翻车的从来不是“命令写错”,而是「命令返回成功,但结果不在你以为的地方」。 所以每一步都配了一条回查语句 —— 前四条都能在 dba_* 字典里对出来,第五条只能在用户自己的 user_tables 里对。

五步速成:从登录到建出第一张表

点左侧任一步骤,右侧给出该步的命令、实测输出与判断依据。
1用 disql 登录
回显里那行 open 才是登录成功的证据
点击查看命令 →
2建一个属于业务的表空间
集群里文件落在哪个节点不由你决定
点击查看命令 →
3建用户,把默认表空间钉死
建完不查,等于没建
点击查看命令 →
4授权,并搞清楚每个角色到底给了什么
RESOURCE 干活、SOI 让元数据可见、VTI 是空的
点击查看实测 →
5建表,验证它真的在指定表空间里
user_tables 那一列是唯一硬证据
点击查看命令 →
步骤明细 已固定

左侧点一步,这里显示该步的完整命令与实测输出。点同一块可取消固定,按 Esc 也可取消。

这次实测的环境:DM Database Server 64 V8,版本号 03134284172-20260803-340005-20093, 四实例 DP 集群(MP 5239 / SP1 5236 / BP1 5237 / BP2 5238),全部 OPEN。 下面所有输出都是从这个环境里原样取的,没有改写、没有补全。

两种连法:带主机端口,或本机 socket。日常交付用第一种,因为客户现场几乎不会让你登到数据库主机上。

# 连指定主机和端口(交付时最常用)
./disql <用户名>/<口令>@<IP>:<端口>

# 连本机默认实例(省掉 IP 和端口)
./disql <用户名>/<口令>

# 口令不方便写在命令行时:先连上,再交互式改连
./disql /nolog
SQL> conn <用户名>/<口令>@<IP>:<端口>
实测输出(登录成功的回显)
Server[127.0.0.1:5236]:mode is normal, state is open
login used time : 2.762(ms)
disql V8
SQL>
第一行才是登录成功的证据:mode is normal, state is open。看到这行才说明实例是正常打开状态; 如果实例在 mount 状态,这行会变成 mode is normal, state is mount,后面建表一律失败。
坑一:口令里有 #,disql 会打一堆用法说明
$ ./disql DELIVERY/"Deliv_2026#01"@127.0.0.1:5236
 USAGE:CONN[ECT] <logon>
 ...
 <logon_option> ::= #{<extend_option>=<value>[,...]}...
原因是 disql 的登录串语法里 # 是扩展选项分隔符(#{MPP_TYPE=GLOBAL,...}), #01@127.0.0.1:5236 被当成了一个格式不对的扩展选项。这不是口令错, 但它长得像语法错误,很容易被误判成版本问题去查半天。
做法:交付时给业务用户设口令避开 #;已经设了就用 /nolog 再 conn 交互输入。
坑二:口令错的时候,disql 不退出,而是掉回交互输入
$ ./disql SYSDBA/WrongPwd@127.0.0.1:5236
[-2501]:Invalid username or password.
disql V8
username:
写在脚本里,这一行 username: 就会把整个自动化流程挂住等输入。 脚本一律加 -L(只尝试一次,失败即退):
./disql -L <用户名>/<口令>@<IP>:<端口> -e "select 1"
顺带一个集群特征:连 SP1 之后查 v$instance,返回的是全部 4 个节点,不是“你连的那一个”。 想知道自己到底连到谁,看登录回显里那行 Server[IP:端口],或者单独查 v$parameter 里的 INSTANCE_NAME。

给业务数据一块独立的存放区,别都堆在 MAIN 上。一条语句建完,顺手带回查。

CREATE TABLESPACE <表空间名>
  DATAFILE '<数据文件名>.DBF'
  SIZE <初始大小 MB>
  AUTOEXTEND ON NEXT <每次扩展 MB> MAXSIZE <上限 MB>;

-- 回查:状态 0 = ONLINE;1 = OFFLINE
SELECT TABLESPACE_NAME, STATUS
  FROM DBA_TABLESPACES
 WHERE TABLESPACE_NAME = '<表空间名>';

SELECT TABLESPACE_NAME, FILE_NAME,
       BYTES/1024/1024 AS MB, AUTOEXTENSIBLE
  FROM DBA_DATA_FILES
 WHERE TABLESPACE_NAME = '<表空间名>';
实测输出(命令是在 SP1 上执行的)
TABLESPACE_NAME STATUS
--------------- -----------
TS_DELIVERY     0

TABLESPACE_NAME FILE_NAME                                       MB    AUTOEXTENSIBLE
--------------- ----------------------------------------------- ----- --------------
TS_DELIVERY     /home/dmdba/dpc_data/bp1/DAMENG/TS_DELIVERY.DBF 128   YES
注意第二张表的路径:文件落在 bp1 节点,而命令是在 sp1 上敲的。
集群里的这条差异,运维文档必须写清:SP 节点不承担存储,表空间会被分配到某个 BP 上。 所以「建完去你连的那台机器上找 DBF」是找不到的 —— 以 DBA_DATA_FILES.FILE_NAME 给出的真实路径为准。
更要注意:具体落到哪个 BP 并不固定。同样的语句在不同时间执行,可能落到 bp1 也可能落到 sp1 目录 (本环境两轮实测就落到了不同位置)。所以别把文件路径写死进任何巡检脚本或文档,一律现查。
坑:DDL 在 -e 模式下成功时什么都不打印
DROP USER 这类语句会回 executed successfully, 但 CREATE TABLESPACE / CREATE USER 在 -e 模式下是静默的。 静默既可能是成功也可能是被吞掉的错误,所以建完立刻回查,这是这套流程里唯一可靠的确认方式。

建一个业务账号,把默认表空间钉在你刚建的那个上。默认表空间决定了这个用户以后不写表空间时数据往哪放。

CREATE USER <用户名>
  IDENTIFIED BY "<口令>"
  DEFAULT TABLESPACE <表空间名>;

-- 交付后客户要换口令,就是这个语句
ALTER USER <用户名> IDENTIFIED BY "<新口令>";

-- 回查:默认表空间和账号状态
SELECT USERNAME, DEFAULT_TABLESPACE, ACCOUNT_STATUS
  FROM DBA_USERS
 WHERE USERNAME = '<用户名>';
实测输出
USERNAME DEFAULT_TABLESPACE ACCOUNT_STATUS
-------- ------------------ --------------
DELIVERY TS_DELIVERY        OPEN
ACCOUNT_STATUS 是 OPEN 才能登录;如果是 LOCKED,说明账号被锁了,得先 ALTER USER ... UNLOCK。
口令怎么写:DM 默认的口令策略会校验长度和字符组成。实际设置时避开 #(见第 1 步的坑), 其余字母数字下划线组合都能过。改完口令必须用新口令登一次才算验完 —— ALTER USER 同样是静默成功,不登一次你并不知道改没改上。

按现场口径授 RESOURCE / VTI / SOI,然后逐个查这三个角色到底带了什么权限。

-- 授权
GRANT RESOURCE, VTI, SOI TO <用户名>;

-- 回查:这个用户当前有哪些角色
SELECT GRANTED_ROLE
  FROM DBA_ROLE_PRIVS
 WHERE GRANTEE = '<用户名>'
 ORDER BY 1;

-- 查每个角色到底带了什么(系统权限 / 对象权限)
SELECT GRANTEE, COUNT(*) AS CNT FROM DBA_SYS_PRIVS
 WHERE GRANTEE IN ('RESOURCE','SOI','VTI') GROUP BY GRANTEE;
SELECT GRANTEE, COUNT(*) AS CNT FROM DBA_TAB_PRIVS
 WHERE GRANTEE IN ('RESOURCE','SOI','VTI') GROUP BY GRANTEE;
SELECT GRANTEE, GRANTED_ROLE FROM DBA_ROLE_PRIVS
 WHERE GRANTEE IN ('RESOURCE','SOI','VTI');
实测输出(授权前 → 授权后)
-- 授权前,只有 PUBLIC(建用户自动带)
GRANTED_ROLE
------------
PUBLIC

-- 授权后
GRANTED_ROLE
------------
PUBLIC
RESOURCE
SOI
VTI
PUBLIC 不需要授,建用户时就有。它已经包含「对自己 schema 里对象」的 SELECT / INSERT / UPDATE / DELETE / EXECUTE 以及建删对象的基础权限(实测 45 条)。
角色 系统权限 对象权限 嵌套角色 实际作用(实测)
RESOURCE 63 条 0 0 CREATE TABLE / INDEX / VIEW / SEQUENCE / PACKAGE / PROCEDURE / TRIGGER,FLASHBACK TABLE,对自己对象的 DML,以及把权限转授给别人
SOI 0 78 0 对 78 个系统字典表的 SELECT:SYSCOLUMNS、SYSOBJECTS、SYSCONS、DPC_INSTANCE、DPC_LONG_TRX 等 —— 元数据查得到的来源
VTI 0 0 0 空角色:授予不报错、撤销不报错,不提供任何权限
VTI 是空的,这件事做了对照实验才敢说:
-- 撤掉 VTI,用业务用户查实例信息
REVOKE VTI FROM DELIVERY;
SQL> select count(*) c from v$instance;
LINEID     C
---------- --------------------
1          4

-- 再授回 VTI,同一条语句
GRANT VTI TO DELIVERY;
SQL> select count(*) c from v$instance;
LINEID     C
---------- --------------------
1          4
撤与不撤结果完全一样。也就是说「能查 v$instance」这件事不是 VTI 给的。 想让非 DBA 用户看某个动态视图,正确做法是单独授: GRANT SELECT ON <v$视图名> TO <用户名>;
越权时的报错措辞会骗人:
SQL> select count(*) from sys.sysobjects;    -- 成功:1152
SQL> select count(*) from dba_users;         -- [-5504]:No select privilege on object [SYS.DBA_USERS]
SQL> select count(*) from SYSDBA.T_ORDER;    -- [-2106]:Invalid table or view name [T_ORDER]
查别人 schema 下的表时,DM 报的是「表或视图不存在」而不是「权限不足」。 这是有意为之(不泄露对象是否存在),但排查时极易被读成「表被删了」。 看到 -2106 先想权限,别急着找备份。

用业务身份建表、插两行、查回来。最后一步必须回到 user_tables 看表空间归属。

-- 用业务用户身份执行
CREATE TABLE <表名> (
  order_id   BIGINT IDENTITY(1,1) PRIMARY KEY,
  order_no   VARCHAR(32) NOT NULL,
  amount     DECIMAL(12,2) DEFAULT 0,
  status     TINYINT DEFAULT 0,
  created_at TIMESTAMP DEFAULT SYSDATE
);

INSERT INTO <表名>(order_no, amount, status)
  VALUES ('SO20261029001', 1280.00, 0);
COMMIT;

-- 回查数据
SELECT order_id, order_no, amount, status, created_at FROM <表名>;

-- 关键一问:这张表落在哪个表空间
SELECT TABLE_NAME, TABLESPACE_NAME FROM USER_TABLES;
实测输出
SQL> 2   3   4   5   6   7   executed successfully
used time: 28.171(ms). Execute id is 12584813.
SQL> affect rows 1
SQL> affect rows 1
SQL> executed successfully

SQL> select order_id, order_no, amount, status, created_at from T_ORDER;
LINEID  ORDER_ID  ORDER_NO       AMOUNT  STATUS  CREATED_AT
------  --------  -------------  ------  ------  --------------------------
1       1         SO20261029001  1280    0       2026-10-29 23:32:06.000000
2       2         SO20261029002  3560.5  1       2026-10-29 23:32:06.000000

SQL> select table_name, tablespace_name from user_tables;
LINEID  TABLE_NAME  TABLESPACE_NAME
------  ----------  ---------------
1       T_ORDER     TS_DELIVERY
TABLESPACE_NAME = TS_DELIVERY 是「默认表空间真的生效了」的唯一硬证据。 CREATE USER ... DEFAULT TABLESPACE 成功只说明语句过了,不说明后续建表会落进去。
顺带确认两件事:IDENTITY(1,1) 从 1 开始且不需要序列; DEFAULT SYSDATE 在插入时自动填了当前时间(两行时间戳相同,因为同一次提交)。

交付前核查清单:六条,全部可以在命令行里对出来

交付完别急着走,按这张表逐条走一遍,每条都有明确的合格标准。
要确认的事 怎么查 合格标准
1 业务用户能登录 用新用户执行一次 disql 用户/口令@IP:端口 回显 mode is normal, state is open,且进到 SQL> 提示符
2 默认表空间已钉住 select DEFAULT_TABLESPACE from DBA_USERS where USERNAME='...' 等于你指定的那个表空间名
3 表真的落在里面 select TABLESPACE_NAME from USER_TABLES(用业务身份) 等于同一个表空间名
4 该给的权限到位 select GRANTED_ROLE from DBA_ROLE_PRIVS where GRANTEE='...' 含 RESOURCE 与 SOI(PUBLIC 自动带)
5 不该给的没给 用业务身份试 select count(*) from dba_users 报 [-5504]:No select privilege —— 报错才是对的
6 口令能改、改完能登 ALTER USER ... IDENTIFIED BY "..." 后用新口令登录 登录成功。不登一次就等于没验
第 5 条特别说明:这一条是「反向验证」。只验「该给的给了」是不够的, 还要验「不该给的没给」—— 否则一次手误授了 DBA,前面五项全都正常,问题却埋在那儿。

常见问题

两个原因叠在一起,但都不是权限的锅:

① 本版本里 VTI 是空角色(系统权限 0 / 对象权限 0 / 嵌套角色 0),授它不产生任何权限;

② v$session 在这个集群版本里根本不存在。实测以 SYSDBA 身份 GRANT SELECT ON v$session TO 用户 会直接报 [-2201]:Invalid database object.;以业务身份查询报 [-2106]:Invalid table or view name [V$SESSION].

会话与节点信息走 DPC_* 系列(DPC_INSTANCE、DPC_LONG_TRX、DPC_HOST 这些), 而它们在 SOI 授予的 78 个对象里,不需要额外授权。

因为集群里 SP 节点不做存储。表空间会被分配到某个 BP 上,文件就落在那个 BP 的目录里。

以 DBA_DATA_FILES.FILE_NAME 为准。本环境实测:在 SP1(5236)上建的表空间,文件落在 bp1 的 dpc_data/bp1/DAMENG/ 下。

而且落到哪个 BP 不固定 —— 同样的语句两轮实测落到了不同位置,所以路径只能现查,不能写死。

数据库本身允许,但 disql 命令行传参时会出问题:# 在登录串里是扩展选项分隔符 (#{MPP_TYPE=GLOBAL,...}),用户/口令#xxx@IP:端口 会被解析成一个坏掉的扩展选项, disql 直接打印用法说明。

交付时给业务用户设口令避开 # 最省事;已经这么设了,用 disql /nolog 再 conn 用户/口令@IP:端口 交互输入即可。

能收,但没什么理由收:它给的是「对自己 schema 里对象」的基础 DML 和执行权限, 本来就是这个用户该有的东西(实测 45 条)。真回收了,用户连自己的表都操作不了。

要收紧权限,正确方向是别多授系统权限和角色(尤其是 DBA),而不是去动 PUBLIC。

因为 CREATE TABLESPACE / CREATE USER / ALTER USER 在 -e 模式下 成功时什么都不打印。同样一行空白,既可能是成功,也可能是错误被吞了。

只有字典表里的那一行是硬的。这套流程里凡是“看起来成了”的地方,都配了一条回查语句。

本篇的边界

不能直接照抄的部分:本文所有输出取自 DMDPC 四实例集群(MP/SP1/BP1/BP2)。 单机实例上的差异有两处要自己再确认:
① 表空间数据文件路径固定在本机,不存在“落到哪个 BP”的问题;
② v$instance 只返回一行,而不是四行。
另外,各版本的角色内容可能不同 —— VTI 在本版本(03134284172-20260803)是空角色, 不代表你手上的版本也一定是。用第 4 步那三条 dba_* 查询自己跑一遍,比记结论可靠。

卡在某一步了?

把报错原文贴出来,比描述现象有用得多。
微信二维码
扫码加微信
备注「达梦」
贴什么最有帮助

① 完整报错行(含 [-NNNN] 错误码,DM 的错误码是排查入口);
② 你执行的那条语句原文(口令打码);
③ select banner from v$version; 的输出 —— 版本不同,行为可能不同。

不要贴什么

生产库的连接串、真实口令、客户业务表的表结构。定位问题不需要这些。

邮件:jiang-chuang@qq.com

想让答案别人也能查到?在 Gitee 仓库 提 issue,回复公开可查。

← 返回指南索引