达梦 DM 常用运维指令手册

运维指令手册 43.6 KB 原文

达梦 DM 常用运维指令手册

适用版本:DM8(生产主线,含 8.1.2.x / 8.1.3.x),附 DM9 现状说明 约定:# root 或 dmdba,$ dmdba 用户,SQL> disql 提示符,<xxx> 为占位符。 差异标注:正文用 > **版本差异** 引用块标注跨版本不一致之处。 更新时间:2026-11


目录

  1. 版本现状与选型判断
  2. 架构与目录约定
  3. 下载与安装
  4. 数据库初始化(dminit)
  5. 服务管理与启停
  6. disql 客户端
  7. 参数管理
  8. 用户、角色与权限
  9. 表空间与数据文件
  10. 库表对象与分区
  11. 备份与恢复(dmrman)
  12. 逻辑导出导入(dexp / dimp)
  13. 归档与 PITR
  14. 数据守护(Data Watch)
  15. DMDSC 共享存储集群
  16. 日志与监控
  17. 性能诊断
  18. 空间与容量管理
  19. 升级与迁移
  20. 高频故障速查
  21. 危险命令与避坑清单
  22. 附录:一键巡检脚本

1. 版本现状与选型判断

1.1 DM8 与 DM9 的真实状态

这是本手册最需要说清楚的一件事,因为网上的信息普遍超前于实际可用性。

项 DM8 DM9
发布时间 长期主线,8.1.2.x / 8.1.3.x 持续打补丁 2026-04-22 发布
安装介质 官网公开下载 2026-08-19 才上线测试版
官方文档 完整(安装、系统管理员、SQL、dminit、disql、备份还原等全套) 截至 2026-09,文档站只有 DM8 手册
生产可用性 成熟,存量占绝对多数 早期试用,不建议核心系统上线
国测等级 集中式 Ⅱ 级(DM9 也拿了 Ⅱ 级) 集中式 + 分布式双 Ⅱ 级
新特性 — 450+ 项,含向量/多模、AI 智能体、共享存储集群、全密态

结论(重要):

  1. 现在要做生产运维,请按 DM8 准备,本手册主体也按 DM8 写;
  2. DM9 的介质覆盖 Windows / CentOS 7 / 麒麟 V10 SP1,架构覆盖 x86 / 鲲鹏 920 / 飞腾 2000,但是测试版;
  3. DM9 的命令行体系(dminit、disql、dmrman、dexp/dimp、dmwatcher)与 DM8 高度一致,DM8 的技能可以直接迁移,主要差异在新特性上;
  4. 如果立项文档要写版本,建议写「DM8 最新补丁版」,不要写「DM9」——验收时文档缺失会成为硬伤。

1.2 版本识别

-- 数据库版本(含 build 时间)
SELECT * FROM V$INSTANCE;
SELECT BUILD_VERSION, BUILD_TIME FROM V$INSTANCE;

-- 更简洁
SELECT ID_CODE();
# 二进制版本
$DM_HOME/bin/dmserver -h 2>&1 | head -5

1.3 兼容模式

DM 通过 COMPATIBLE_MODE 参数模拟其他数据库的行为:

值 兼容 说明
0 不兼容 DM 原生语法
1 Oracle 最常用,ROWNUM、NVL、DUAL、PL/SQL
2 MySQL 反引号、LIMIT、AUTO_INCREMENT
3 SQL Server TOP、@@IDENTITY
4 DB2 —
5 Teradata —
6 PostgreSQL 部分版本支持
-- 查看
SELECT PARA_NAME, PARA_VALUE FROM V$DM_INI WHERE PARA_NAME = 'COMPATIBLE_MODE';

-- 修改(静态参数,需重启)
SP_SET_PARA_VALUE(2, 'COMPATIBLE_MODE', 1);

COMPATIBLE_MODE 是静态参数,改完必须重启。而且它影响的是解析层行为,不同模式下同一条 SQL 可能返回不同结果。切换前必须在测试库回归,不要在生产直接改。


2. 架构与目录约定

2.1 单机架构

客户端(disql / JDBC / ODBC / .NET)
        │  5236
   ┌────▼─────┐
   │ dmserver │  数据库主进程(多线程)
   └────┬─────┘
        │
   ┌────▼────────────────────────┐
   │ 数据文件 / 联机日志 / 归档日志 │
   └─────────────────────────────┘

辅助进程:
  DmAPService   备份辅助(dmrman 依赖,必须启动)
  DmServiceXXX  注册的数据库服务
  dmwatcher     数据守护守护进程
  dmmonitor     数据守护监视器
  dmcss/dmcssm  DMDSC 集群同步服务

2.2 目录结构

路径 内容
/opt/dmdbms($DM_HOME) 安装目录
$DM_HOME/bin dmserver、disql、dmrman、dexp、dimp、dmfldr、服务脚本
$DM_HOME/bin/dm.key License 文件
$DM_HOME/data/DAMENG/dm.ini 实例配置文件(最关键)
$DM_HOME/data/DAMENG/ 数据文件 .DBF、联机日志 DAMENG01.log
$DM_HOME/log/ 运行日志 dm_DMSERVER_YYYYMM.log
/dm/arch(自定义) 归档日志目录
/dm/bak(自定义) 备份目录
# 环境变量(dmdba 用户)
export DM_HOME=/opt/dmdbms
export PATH=$DM_HOME/bin:$PATH
export LD_LIBRARY_PATH=$DM_HOME/bin:$LD_LIBRARY_PATH

dm.ini 是实例的身份证。dmserver 启动时必须显式指定它的路径(dmserver /opt/dmdbms/data/DAMENG/dm.ini),一个 dm.ini 对应一个实例。多实例部署时千万不要搞混路径——启错实例是达梦运维最典型的事故。

2.3 默认端口与账号

项 默认值
端口 5236
系统管理员 SYSDBA / SYSDBA
安全管理员 SYSSSO(三权分立时)
审计管理员 SYSAUDITOR
实例名 DMSERVER
数据库名 DAMENG
-- 查看端口
SELECT PARA_NAME, PARA_VALUE FROM V$DM_INI WHERE PARA_NAME = 'PORT_NUM';

3. 下载与安装

3.1 官方入口

用途 地址
官网 https://www.dameng.com/
下载中心 https://www.dameng.com/list_103.html
技术社区 https://eco.dameng.com/
在线文档 https://eco.dameng.com/document/dm/zh-cn/pm/
驱动下载 https://eco.dameng.com/download/

达梦的安装包需要在官网注册后下载,且分 x86 / ARM / 龙芯 / 申威等多个架构版本。下载时注意核对:dm8_2024xxxx_x86_rh7_64.iso 这类文件名里已经标了架构和 OS。

3.2 环境准备

# 1) 创建用户组与用户
groupadd dinstall
useradd -g dinstall -m -d /home/dmdba -s /bin/bash dmdba
echo 'Dmdba@123' | passwd --stdin dmdba

# 2) 目录
mkdir -p /opt/dmdbms /dm/data /dm/arch /dm/bak
chown -R dmdba:dinstall /opt/dmdbms /dm
chmod -R 755 /opt/dmdbms /dm

# 3) 资源限制
cat >> /etc/security/limits.conf <<'EOF'
dmdba soft nofile 65536
dmdba hard nofile 65536
dmdba soft nproc  65536
dmdba hard nproc  65536
dmdba soft stack  unlimited
dmdba hard stack  unlimited
EOF

# 4) 内核参数
cat >> /etc/sysctl.conf <<'EOF'
vm.swappiness = 0
vm.dirty_ratio = 20
vm.dirty_background_ratio = 10
kernel.shmmax = 68719476736
kernel.shmall = 4294967296
fs.file-max = 6815744
net.core.somaxconn = 4096
EOF
sysctl -p

# 5) 关闭 SELinux / 防火墙
setenforce 0
systemctl stop firewalld

# 6) 时间同步
systemctl enable --now chronyd

3.3 安装

# 挂载 ISO
mount -o loop dm8_2024xxxx_x86_rh7_64.iso /mnt/dm

# 静默安装(推荐,可脚本化)
su - dmdba
cd /mnt/dm
./DMInstall.bin -q /tmp/dm_install.xml
<!-- /tmp/dm_install.xml 最小配置 -->
<?xml version="1.0"?>
<DATABASE>
  <LANGUAGE>zh_CN</LANGUAGE>
  <TIME_ZONE>+08:00</TIME_ZONE>
  <KEY></KEY>
  <INSTALL_TYPE>0</INSTALL_TYPE>
  <INSTALL_PATH>/opt/dmdbms</INSTALL_PATH>
</DATABASE>
# 图形化安装(有桌面环境时)
./DMInstall.bin

# 安装完成后,按提示用 root 执行脚本
/opt/dmdbms/script/root/root_installer.sh
# 验证
ls -l /opt/dmdbms/bin/dmserver
/opt/dmdbms/bin/disql -h

3.4 License

# 查看 License 信息
cat /opt/dmdbms/bin/dm.key | head -5
SELECT * FROM V$LICENSE;
-- 关注:授权用户数、有效期、是否集群授权

DM8 的 License 分单机版 / 集群版 / 只读版,以及按 CPU 核数或用户数授权。集群版 License 才能跑数据守护和 DMDSC,用单机 License 配守护会在启动 dmwatcher 时报授权错误。这是实施阶段最常见的「买了但用不了」。


4. 数据库初始化(dminit)

4.1 dminit 参数

$DM_HOME/bin/dminit help
参数 默认 说明
PATH 必填 数据文件存放路径
DB_NAME DAMENG 数据库名
INSTANCE_NAME DMSERVER 实例名
PORT_NUM 5236 监听端口
PAGE_SIZE 8 KB 页大小,4/8/16/32
EXTENT_SIZE 16 簇大小(页数),16/32
CASE_SENSITIVE Y 大小写敏感,建库后不可改
CHARSET 0 0=GB18030,1=UTF-8,2=EUC-KR
LENGTH_IN_CHAR N VARCHAR 长度按字符还是字节
SYSDBA_PWD 同用户名 SYSDBA 初始密码
BUFFER 计算值 数据缓冲区大小(MB)
MAX_SESSIONS 100 最大会话数
# 标准初始化(推荐配置)
su - dmdba
$DM_HOME/bin/dminit \
  PATH=/dm/data \
  DB_NAME=DAMENG \
  INSTANCE_NAME=DMSERVER \
  PORT_NUM=5236 \
  PAGE_SIZE=16 \
  EXTENT_SIZE=16 \
  CASE_SENSITIVE=Y \
  CHARSET=1 \
  LENGTH_IN_CHAR=Y \
  SYSDBA_PWD='Dameng@2026' \
  BUFFER=4096 \
  MAX_SESSIONS=1000

三个建库后不可改的参数:PAGE_SIZE、CASE_SENSITIVE、CHARSET(以及 LENGTH_IN_CHAR)。选错只能重建库。

  • PAGE_SIZE=16 或 32 对含大量 VARCHAR/CLOB 的表更友好,但页越大单页 IO 越重;
  • CASE_SENSITIVE=Y 时 "Table" 与 "table" 是两个对象,从 MySQL 迁过来建议设 N;
  • CHARSET=1(UTF-8)是当前标准选择,0(GB18030)仅用于老旧系统。

4.2 启动数据库

# 前台启动(调试用,Ctrl+C 会停库)
$DM_HOME/bin/dmserver /dm/data/DAMENG/dm.ini

# 后台启动(nohup)
nohup $DM_HOME/bin/dmserver /dm/data/DAMENG/dm.ini > /dev/null 2>&1 &

# 指定启动到 MOUNT 状态(维护用)
$DM_HOME/bin/dmserver /dm/data/DAMENG/dm.ini mount

4.3 注册系统服务

# 用 root 注册(推荐,便于 systemd 管理)
/opt/dmdbms/script/root/dm_service_installer.sh \
  -t dmserver \
  -dm_ini /dm/data/DAMENG/dm.ini \
  -p DMSERVER

# 生成的服务名:DmServiceDMSERVER
systemctl start DmServiceDMSERVER
systemctl status DmServiceDMSERVER
systemctl enable DmServiceDMSERVER

# 其他服务类型
# -t dmap            备份辅助服务(必须装)
# -t dmwatcher       数据守护
# -t dmmonitor       监视器
# -t dmcss           DMDSC 集群同步
# -t dmcssm          DMDSC 监视器

# 注册 dmap(备份的前置条件)
/opt/dmdbms/script/root/dm_service_installer.sh -t dmap
systemctl start DmAPService
# 卸载服务
/opt/dmdbms/script/root/dm_service_uninstaller.sh -n DmServiceDMSERVER

DmAPService 不启动,dmrman 备份会失败。报错通常是「备份管道连接失败」或「dmap 未启动」,很多人会误以为是备份路径问题。装完库第一件事就是把 dmap 拉起来并设开机自启。


5. 服务管理与启停

5.1 三种启停方式

方式 命令 适用
systemd systemctl start/stop DmServiceDMSERVER 注册了服务,生产推荐
达梦服务脚本 $DM_HOME/bin/DmServiceDMSERVER start 兼容老部署
直接启进程 dmserver /path/dm.ini 调试、单次维护
# systemd
systemctl start DmServiceDMSERVER
systemctl stop DmServiceDMSERVER
systemctl restart DmServiceDMSERVER
systemctl status DmServiceDMSERVER

# 达梦脚本
$DM_HOME/bin/DmServiceDMSERVER start
$DM_HOME/bin/DmServiceDMSERVER stop
$DM_HOME/bin/DmServiceDMSERVER status

# 正常退出(SQL 方式,最安全)
-- 用 SQL 关库(会等事务结束)
SHUTDOWN;
-- 立即关闭(回滚未提交事务)
SHUTDOWN IMMEDIATE;
-- 强制关闭(可能需恢复)
-- 不推荐,仅在 hang 死时用

不要 kill -9 dmserver。DM 的共享内存段和信号量不会自动释放,重启时可能报「共享内存创建失败」,需要手工 ipcrm 清理。优先用 SHUTDOWN IMMEDIATE。

5.2 启动状态

DM 有三种启动状态:

状态 说明 可做什么
MOUNT 加载了 dm.ini 和控制文件,未打开数据文件 改归档模式、改 COMPATIBLE_MODE、恢复
OPEN 完全打开,可读写 正常业务
NORMAL 未加载 —
-- 查看当前状态
SELECT STATUS$ FROM V$INSTANCE;
-- 或
SELECT * FROM V$INSTANCE;
-- MOUNT 与 OPEN 切换
ALTER DATABASE MOUNT;
ALTER DATABASE OPEN;

5.3 进程检查

ps -ef | grep dmserver | grep -v grep
ss -lntp | grep 5236
-- 会话与线程
SELECT SESS_ID, USER_NAME, STATE, CREATE_TIME, CLNT_IP, LEFT(SQL_TEXT, 80)
FROM V$SESSIONS WHERE STATE <> 'IDLE' ORDER BY CREATE_TIME;

6. disql 客户端

6.1 连接

# 本机(默认 SYSDBA/SYSDBA)
$DM_HOME/bin/disql SYSDBA/SYSDBA

# 指定主机端口
$DM_HOME/bin/disql SYSDBA/'Dameng@2026'@10.0.0.11:5236

# 连接后切库/切用户
SQL> conn TEST/'Test@123'@10.0.0.11:5236

# 免交互执行
$DM_HOME/bin/disql -S SYSDBA/SYSDBA -e "SELECT COUNT(*) FROM TEST.T1;"

密码含特殊字符要加引号:disql SYSDBA/'P@ss#2026'@host:port。不加引号时 @ 会被当成主机分隔符,报「无效的主机名」。这是 disql 最常见的连接失败原因。

6.2 常用命令

-- 会话设置(每个 disql 会话都要重设,不持久)
SET TIMING ON;            -- 显示执行时间
SET LINESIZE 300;         -- 行宽
SET PAGESIZE 1000;        -- 每页行数(0 = 不分页)
SET HEADING ON;
SET ECHO OFF;
SET DEFINE OFF;           -- 关闭 & 变量替换(脚本里有 & 时必设)

-- 执行脚本
START /dm/script/init.sql;
`/dm/script/init.sql

-- 输出到文件
SPOOL /tmp/out.txt;
SELECT * FROM TEST.T1;
SPOOL OFF;

-- 查看帮助
HELP
HELP SELECT

-- 退出
EXIT

6.3 常用查询

-- 当前用户
SELECT USER FROM DUAL;

-- 数据库信息
SELECT * FROM V$DATABASE;
SELECT * FROM V$INSTANCE;

-- 表列表
SELECT OWNER, TABLE_NAME, NUM_ROWS FROM DBA_TABLES WHERE OWNER = 'TEST';

-- 表结构
SELECT COLUMN_NAME, DATA_TYPE, DATA_LENGTH, NULLABLE
FROM DBA_TAB_COLUMNS WHERE OWNER='TEST' AND TABLE_NAME='T1' ORDER BY COLUMN_ID;

-- 执行计划
EXPLAIN SELECT * FROM TEST.T1 WHERE ID = 1;

7. 参数管理

7.1 参数查询

-- 全部参数
SELECT PARA_NAME, PARA_VALUE, PARA_TYPE, MIN_VALUE, MAX_VALUE
FROM V$DM_INI ORDER BY PARA_NAME;

-- 模糊查
SELECT PARA_NAME, PARA_VALUE FROM V$DM_INI WHERE PARA_NAME LIKE '%BUFFER%';

-- 当前生效值(含会话级)
SELECT NAME, VALUE, TYPE FROM V$PARAMETER WHERE NAME LIKE '%SORT%';

-- 参数说明
SELECT * FROM V$DM_INI WHERE PARA_NAME = 'MEMORY_POOL';

7.2 参数修改

达梦用存储过程改参数,SP_SET_PARA_VALUE 的第一个参数是修改范围:

范围值 含义 生效方式
1 内存 + 配置文件 动态参数立即生效,静态参数重启生效
2 仅配置文件 重启生效
-- 改整型
SP_SET_PARA_VALUE(1, 'MAX_SESSIONS', 2000);

-- 改浮点
SP_SET_PARA_DOUBLE_VALUE(1, 'SORT_BUF_SIZE', 64.0);

-- 改字符串
SP_SET_PARA_STRING_VALUE(1, 'SVR_LOG', '/dm/log/svr.log');

-- 读回确认
SELECT PARA_NAME, PARA_VALUE FROM V$DM_INI WHERE PARA_NAME = 'MAX_SESSIONS';
-- 会话级参数(只影响当前会话)
SET SORT_BUF_SIZE = 64;

SP_SET_PARA_VALUE(1, ...) 对静态参数只写文件不生效,命令不报错,容易误判。改完必须 SELECT PARA_VALUE FROM V$DM_INI 确认,静态参数还要重启。判断方法:V$DM_INI.PARA_TYPE,或直接看是否需要重启的官方参数表。

7.3 关键参数

参数 默认 建议 说明
MEMORY_POOL 100 MB 500~2000 内存池,影响并发能力
BUFFER 计算值 物理内存 40%~60% 数据缓冲区(MB),最影响性能
MAX_BUFFER 计算值 BUFFER 的 1.2 倍 缓冲区上限,用于动态扩展
MAX_SESSIONS 100 1000~3000 最大会话数
MAX_SESSION_STATEMENT 100 100 每会话保留的语句数
SORT_BUF_SIZE 2 MB 16~64 排序缓冲
HJ_BUF_SIZE 计算值 64~256 Hash Join 缓冲
TEMP_SIZE 10 MB 100~1024 临时表空间初始大小(MB)
TEMP_SPACE_LIMIT 0 10240~102400 临时空间上限(MB),0 = 不限
RLOG_BUF_SIZE 1024 KB 4096 联机日志缓冲
SVR_LOG 0 1(开启) SQL 日志开关
ENABLE_MONITOR 1 1 开启监控(性能视图依赖它)
COMPATIBLE_MODE 0 1(Oracle)/2(MySQL) 兼容模式,静态
ARCH_INI 0 1(开启归档) 归档配置开关
PWD_POLICY 2 按等保要求 口令策略位掩码
OLAP_FLAG 2 2 OLAP 优化级别
WORKER_THREADS 计算值 按并发调 工作线程数
-- 一批常用调整(生产初始化后建议执行)
SP_SET_PARA_VALUE(1, 'MAX_SESSIONS', 2000);
SP_SET_PARA_VALUE(1, 'MEMORY_POOL', 1000);
SP_SET_PARA_VALUE(1, 'SORT_BUF_SIZE', 32);
SP_SET_PARA_VALUE(1, 'TEMP_SPACE_LIMIT', 51200);
SP_SET_PARA_VALUE(1, 'ENABLE_MONITOR', 1);
-- 以下为静态参数,需重启
SP_SET_PARA_VALUE(2, 'BUFFER', 8192);
SP_SET_PARA_VALUE(2, 'MAX_BUFFER', 10240);

BUFFER 是达梦最重要的性能参数。经验值:专用数据库服务器给物理内存的 50%~60%,与 MEMORY_POOL、HJ_BUF_SIZE、SORT_BUF_SIZE 之和不超过物理内存的 80%。给太多会 OOM,给太少会频繁读盘。


8. 用户、角色与权限

8.1 用户管理

-- 建用户
CREATE USER TEST IDENTIFIED BY "Test@12345"
  DEFAULT TABLESPACE TEST_TS
  DEFAULT INDEX TABLESPACE TEST_IDX;

-- 授权
GRANT DBA TO TEST;                      -- 高危,仅管理员
GRANT RESOURCE TO TEST;                 -- 建表等
GRANT PUBLIC TO TEST;

-- 细粒度授权
GRANT SELECT, INSERT, UPDATE, DELETE ON TEST.T1 TO APP;
GRANT SELECT ON TEST.V1 TO READONLY;
GRANT EXECUTE ON PROCEDURE TEST.P1 TO APP;

-- 改密
ALTER USER TEST IDENTIFIED BY "New@12345";

-- 锁定/解锁
ALTER USER TEST ACCOUNT LOCK;
ALTER USER TEST ACCOUNT UNLOCK;

-- 密码有效期
ALTER USER TEST LIMIT PASSWORD_LIFE_TIME 90;

-- 查看
SELECT USERNAME, ACCOUNT_STATUS, DEFAULT_TABLESPACE, CREATED, EXPIRY_DATE
FROM DBA_USERS;

-- 删除
DROP USER TEST CASCADE;

DROP USER ... CASCADE 会连带删除该用户所有对象,且达梦默认不进回收站。执行前必须确认,或先 SELECT COUNT(*) FROM DBA_TABLES WHERE OWNER='TEST'。

8.2 角色

-- 建角色
CREATE ROLE RO_APP;

-- 给角色授权
GRANT SELECT ON TEST.T1 TO RO_APP;
GRANT SELECT ON TEST.V1 TO RO_APP;

-- 角色给用户
GRANT RO_APP TO APP;

-- 查看
SELECT * FROM DBA_ROLES;
SELECT * FROM DBA_ROLE_PRIVS WHERE GRANTEE = 'APP';

-- 删除
DROP ROLE RO_APP;
内置角色 权限
DBA 全部权限,生产慎用
RESOURCE 建表、建索引、建视图
PUBLIC 默认公共角色,所有用户都有
VTI 动态视图查询
SOI 系统表查询

8.3 三权分立

等保要求下需要把 SYSDBA 的权限拆开:

-- 开启三权分立(需重启)
SP_SET_PARA_VALUE(2, 'ENABLE_SEPARATION_OF_DUTY', 1);
账号 职责 不能做什么
SYSDBA 系统管理 不能看审计日志、不能管安全策略
SYSSSO 安全管理员 不能操作业务数据
SYSAUDITOR 审计管理员 不能改数据、不能改配置

三权分立开启后,SYSDBA 就不能再建用户了(归 SYSSSO 管),也不能查审计日志。这是合规项目的标准配置,但会显著改变运维习惯,实施前要和客户对齐。

8.4 审计

-- 开启审计
SP_SET_PARA_VALUE(1, 'ENABLE_AUDIT', 1);

-- 审计对象(对 TEST.T1 的所有操作)
AUDIT SELECT, INSERT, UPDATE, DELETE ON TEST.T1;

-- 审计语句
AUDIT TABLE;
AUDIT CREATE TABLE;

-- 查看审计日志(需 SYSAUDITOR 或审计权限)
SELECT * FROM SYSAUDITOR.V$AUDITRECORDS
WHERE TM > TO_DATE('2026-11-01','YYYY-MM-DD') ORDER BY TM DESC;

-- 关闭审计项
NOAUDIT SELECT ON TEST.T1;

9. 表空间与数据文件

9.1 表空间

-- 建表空间(自动扩展)
CREATE TABLESPACE TEST_TS
  DATAFILE '/dm/data/DAMENG/test_ts01.dbf' SIZE 512
  AUTOEXTEND ON NEXT 64 MAXSIZE 20480;

-- 建索引表空间
CREATE TABLESPACE TEST_IDX
  DATAFILE '/dm/data/DAMENG/test_idx01.dbf' SIZE 256
  AUTOEXTEND ON NEXT 64 MAXSIZE 10240;

-- 加大数据文件
ALTER TABLESPACE TEST_TS ADD DATAFILE '/dm/data/DAMENG/test_ts02.dbf' SIZE 1024
  AUTOEXTEND ON NEXT 128 MAXSIZE 20480;

-- 修改现有文件
ALTER DATABASE DATAFILE '/dm/data/DAMENG/test_ts01.dbf' AUTOEXTEND ON NEXT 128 MAXSIZE 30720;

-- 查看
SELECT TABLESPACE_NAME, FILE_NAME, BYTES/1024/1024 AS mb, AUTOEXTEND, MAXBYTES/1024/1024 AS max_mb
FROM DBA_DATA_FILES ORDER BY TABLESPACE_NAME;

-- 表空间使用率
SELECT TS.TABLESPACE_NAME,
       ROUND(SUM(DF.BYTES)/1024/1024, 2) total_mb,
       ROUND(SUM(DF.BYTES)/1024/1024 - NVL(SUM(FS.BYTES)/1024/1024, 0), 2) used_mb,
       ROUND((SUM(DF.BYTES) - NVL(SUM(FS.BYTES),0)) / SUM(DF.BYTES) * 100, 2) used_pct
FROM DBA_DATA_FILES DF
JOIN DBA_TABLESPACES TS ON DF.TABLESPACE_NAME = TS.TABLESPACE_NAME
LEFT JOIN DBA_FREE_SPACE FS ON DF.FILE_ID = FS.FILE_ID
GROUP BY TS.TABLESPACE_NAME ORDER BY used_pct DESC;

9.2 系统表空间

表空间 用途 能否删
SYSTEM 数据字典 绝对禁止
ROLL 回滚记录 绝对禁止
TEMP 临时表、排序 不能删,可扩
MAIN 默认用户表空间 不建议
SYSAUX 系统辅助 不建议
-- 扩 TEMP
ALTER TABLESPACE TEMP ADD DATAFILE '/dm/data/DAMENG/temp02.dbf' SIZE 2048 AUTOEXTEND ON NEXT 256 MAXSIZE 20480;

-- 查看临时空间使用
SELECT * FROM V$TEMPSTAT;

TEMP 满了会导致大查询、排序、建索引全部失败。达梦默认 TEMP_SIZE 只有 10 MB,生产必须调到 100 MB 以上并设 TEMP_SPACE_LIMIT。这是新装库最容易踩的坑。

9.3 数据文件管理

-- 查看文件状态
SELECT FILE_ID, TABLESPACE_NAME, FILE_NAME, STATUS, AUTOEXTEND
FROM DBA_DATA_FILES;

-- 文件 OFFline / ONLINE
ALTER DATABASE DATAFILE '/dm/data/DAMENG/test_ts02.dbf' OFFLINE;
ALTER DATABASE DATAFILE '/dm/data/DAMENG/test_ts02.dbf' ONLINE;

-- 重命名(先 OFFLINE)
ALTER DATABASE DATAFILE '/dm/data/DAMENG/old.dbf' RENAME TO '/dm/data/DAMENG/new.dbf';

10. 库表对象与分区

10.1 建表

-- 普通表
CREATE TABLE TEST.ORDERS (
  ID          BIGINT IDENTITY(1,1) PRIMARY KEY,
  ORDER_NO    VARCHAR(32) NOT NULL,
  USER_ID     BIGINT NOT NULL,
  AMOUNT      DECIMAL(18,2) NOT NULL,
  STATUS      TINYINT DEFAULT 0,
  CREATED_AT  TIMESTAMP DEFAULT SYSDATE,
  CONSTRAINT UK_ORDER_NO UNIQUE(ORDER_NO)
);

-- 指定表空间
CREATE TABLE TEST.LOGS (
  ID BIGINT,
  LOG_TIME TIMESTAMP,
  MSG VARCHAR(2000)
) STORAGE (ON TEST_TS, CLUSTERBTR);

-- 索引
CREATE INDEX IDX_ORDERS_USER ON TEST.ORDERS(USER_ID);
CREATE INDEX IDX_ORDERS_USER_TIME ON TEST.ORDERS(USER_ID, CREATED_AT DESC);
CREATE UNIQUE INDEX UK_ORDERS_NO ON TEST.ORDERS(ORDER_NO);

-- 查看
SELECT * FROM DBA_TABLES WHERE OWNER='TEST';
SELECT * FROM DBA_INDEXES WHERE TABLE_OWNER='TEST' AND TABLE_NAME='ORDERS';

10.2 分区表

-- Range 分区(按时间)
CREATE TABLE TEST.LOGS (
  ID BIGINT,
  LOG_TIME TIMESTAMP NOT NULL,
  MSG VARCHAR(2000)
)
PARTITION BY RANGE (LOG_TIME) (
  PARTITION P202610 VALUES LESS THAN (TO_DATE('2026-11-01','YYYY-MM-DD')),
  PARTITION P202611 VALUES LESS THAN (TO_DATE('2026-12-01','YYYY-MM-DD')),
  PARTITION PMAX    VALUES LESS THAN (MAXVALUE)
);

-- 增加分区(只能加在 MAXVALUE 之前,需先 SPLIT)
ALTER TABLE TEST.LOGS SPLIT PARTITION PMAX AT (TO_DATE('2027-01-01','YYYY-MM-DD'))
  INTO (PARTITION P202612, PARTITION PMAX);

-- 删除分区
ALTER TABLE TEST.LOGS DROP PARTITION P202610;

-- 清空分区(保留结构)
ALTER TABLE TEST.LOGS TRUNCATE PARTITION P202610;

-- 交换分区(把普通表数据换进分区,很快)
ALTER TABLE TEST.LOGS EXCHANGE PARTITION P202611 WITH TABLE TEST.LOGS_TMP;

-- Hash 分区
CREATE TABLE TEST.SESSIONS (
  ID BIGINT,
  DATA VARCHAR(1000)
) PARTITION BY HASH(ID) PARTITIONS 16;
分区类型 语法 适用
Range PARTITION BY RANGE(col) 时间序列、日志
List PARTITION BY LIST(col) 枚举值(地区、类型)
Hash PARTITION BY HASH(col) 打散写入
组合 PARTITION BY RANGE(...) SUBPARTITION BY HASH(...) 大表二级分区

达梦不支持自动新增分区(DM8 无 INTERVAL 分区)。必须用定时任务提前 SPLIT 或 ADD,否则数据会全部落到 PMAX。这是从 Oracle 迁过来最常漏掉的一条。

10.3 统计信息

-- 收集表统计信息
DBMS_STATS.GATHER_TABLE_STATS('TEST', 'ORDERS');

-- 收集 Schema
DBMS_STATS.GATHER_SCHEMA_STATS('TEST');

-- 收集库
DBMS_STATS.GATHER_DATABASE_STATS();

-- 删除统计信息
DBMS_STATS.DELETE_TABLE_STATS('TEST', 'ORDERS');

-- 查看
SELECT OWNER, TABLE_NAME, NUM_ROWS, LAST_ANALYZED FROM DBA_TABLES WHERE OWNER='TEST';
-- 也可以用 SQL 语法(部分版本支持)
ANALYZE TABLE TEST.ORDERS COMPUTE STATISTICS;

达梦没有自动统计信息收集(DM8 默认关闭)。大表数据变化后必须手工收集,否则执行计划会一直走老路径。建议配一个定时任务,每天低峰跑 GATHER_SCHEMA_STATS。

10.4 视图、序列、同义词

-- 视图
CREATE VIEW TEST.V_ORDER_SUM AS
SELECT USER_ID, COUNT(*) CNT, SUM(AMOUNT) TOTAL
FROM TEST.ORDERS GROUP BY USER_ID;

-- 序列
CREATE SEQUENCE TEST.SEQ_ORDER
  START WITH 1 INCREMENT BY 1 CACHE 20 NOCYCLE;

SELECT TEST.SEQ_ORDER.NEXTVAL FROM DUAL;

-- 同义词
CREATE SYNONYM APP.ORDERS FOR TEST.ORDERS;
CREATE PUBLIC SYNONYM ORDERS FOR TEST.ORDERS;

11. 备份与恢复(dmrman)

11.1 备份前置条件

# 1) dmap 服务必须运行
systemctl status DmAPService
systemctl start DmAPService

# 2) 备份目录权限
mkdir -p /dm/bak/full
chown -R dmdba:dinstall /dm/bak
-- 3) 数据库必须是 OPEN 或 MOUNT 状态
SELECT STATUS$ FROM V$INSTANCE;

11.2 SQL 方式备份(最简单)

-- 全量备份(在线,不锁库)
BACKUP DATABASE FULL BACKUPSET '/dm/bak/full/db_full_20261105';

-- 增量备份(需先有全量)
BACKUP DATABASE INCREMENT WITH BACKUPDIR '/dm/bak/full' BACKUPSET '/dm/bak/inc/inc_20261105';

-- 表备份
BACKUP TABLE TEST.ORDERS BACKUPSET '/dm/bak/table/orders_20261105';

-- 归档日志备份
BACKUP ARCHIVE LOG ALL BACKUPSET '/dm/bak/arch/arch_20261105';

-- 查看备份集
SELECT * FROM V$BACKUPSET;
SELECT BACKUP_NAME, BACKUP_TYPE, ROUND(BACKUP_SIZE/1024/1024,2) size_mb,
       BEGIN_TIME, END_TIME
FROM V$BACKUPSET ORDER BY BEGIN_TIME DESC;

-- 查看备份任务历史
SELECT * FROM V$RMAN_BACKUP_JOB_HISTORY ORDER BY BEGIN_TIME DESC;
BACKUP_TYPE 含义
FULL 全量
INCREMENT 增量
TABLE 表级
ARCHIVELOG 归档日志

11.3 dmrman 方式(可离线、可恢复)

# 交互式
$DM_HOME/bin/dmrman

RMAN> BACKUP DATABASE '/dm/data/DAMENG/dm.ini' FULL TO FULL_BAK BACKUPSET '/dm/bak/full/full_20261105';
RMAN> BACKUP DATABASE '/dm/data/DAMENG/dm.ini' INCREMENT TO INC_BAK BACKUPSET '/dm/bak/inc/inc_20261105';
RMAN> CHECK BACKUPSET '/dm/bak/full/full_20261105';
RMAN> EXIT
# 单条命令方式(脚本化推荐)
$DM_HOME/bin/dmrman CTLSTMT="BACKUP DATABASE '/dm/data/DAMENG/dm.ini' FULL TO FULL_BAK BACKUPSET '/dm/bak/full/full_20261105'"

11.4 恢复

# 1) 停库
systemctl stop DmServiceDMSERVER

# 2) 校验备份集
$DM_HOME/bin/dmrman CTLSTMT="CHECK BACKUPSET '/dm/bak/full/full_20261105'"

# 3) 还原(RESTORE 只拷文件)
$DM_HOME/bin/dmrman CTLSTMT="RESTORE DATABASE '/dm/data/DAMENG/dm.ini' FROM BACKUPSET '/dm/bak/full/full_20261105'"

# 4) 恢复(RECOVER 应用归档/联机日志)
$DM_HOME/bin/dmrman CTLSTMT="RECOVER DATABASE '/dm/data/DAMENG/dm.ini' FROM BACKUPSET '/dm/bak/full/full_20261105'"

# 5) 恢复到指定时间点
$DM_HOME/bin/dmrman CTLSTMT="RECOVER DATABASE '/dm/data/DAMENG/dm.ini' WITH ARCHIVEDIR '/dm/arch' UNTIL TIME '2026-11-05 09:30:00'"

# 6) 启动
systemctl start DmServiceDMSERVER

RESTORE 与 RECOVER 必须成对执行。只 RESTORE 不 RECOVER,数据库会处于不一致状态启动失败,报「需要更多恢复」。这是新手最容易漏的一步。

-- 恢复后验证
SELECT STATUS$ FROM V$INSTANCE;
SELECT COUNT(*) FROM TEST.ORDERS;

11.5 表级恢复

# 1) 还原表到临时库(避免覆盖生产)
$DM_HOME/bin/dmrman CTLSTMT="RESTORE TABLE TEST.ORDERS FROM BACKUPSET '/dm/bak/table/orders_20261105'"

# 2) 恢复到临时库
$DM_HOME/bin/dmrman CTLSTMT="RECOVER TABLE TEST.ORDERS FROM BACKUPSET '/dm/bak/table/orders_20261105'"

表级恢复需要 DDL 辅助表(DM8 自动维护 SYSTEM.DM_TABLE_BACKUP),如果表结构变过(加列/删列),恢复可能失败。生产建议用「恢复到临时实例 + INSERT SELECT 回灌」的方式,更可控。

11.6 备份策略

对象 频率 保留 说明
全量 每天 1 次 7 天 低峰,在线备份不锁库
增量 每 6 小时 3 天 基于上次全量
归档日志 持续 7 天 PITR 依赖
逻辑导出 每周 1 次 30 天 dexp 兜底

12. 逻辑导出导入(dexp / dimp)

12.1 导出

# 全库导出
dexp SYSDBA/'Dameng@2026'@10.0.0.11:5236 \
  FILE=/dm/bak/dexp/full_20261105.dmp \
  LOG=/dm/bak/dexp/full_20261105.log \
  FULL=Y

# 按用户导出
dexp SYSDBA/'xxx'@host:5236 \
  FILE=/dm/bak/dexp/test.dmp LOG=/dm/bak/dexp/test.log \
  OWNER=TEST

# 按表导出
dexp SYSDBA/'xxx'@host:5236 \
  FILE=/dm/bak/dexp/orders.dmp LOG=/dm/bak/dexp/orders.log \
  TABLES=TEST.ORDERS

# 带条件导出
dexp SYSDBA/'xxx'@host:5236 \
  FILE=/dm/bak/dexp/orders_2026.dmp \
  TABLES=TEST.ORDERS \
  QUERY="WHERE CREATED_AT >= TO_DATE('2026-01-01','YYYY-MM-DD')"

# 并行 + 压缩(大库提速)
dexp SYSDBA/'xxx'@host:5236 \
  FILE=/dm/bak/dexp/big.dmp LOG=/dm/bak/dexp/big.log \
  OWNER=TEST DIRECT=Y PARALLEL=4 COMPRESS=Y
参数 说明
FULL=Y 全库
OWNER= 按用户
SCHEMAS= 多个 Schema(逗号分隔)
TABLES= 按表(OWNER.TABLE 格式)
QUERY= WHERE 条件
DIRECT=Y 直接路径,跳过 SQL 层,快
PARALLEL=N 并行度,需配合 DIRECT=Y
COMPRESS=Y 压缩
ENCRYPT=Y 加密
ROWS=Y/N 是否导数据

12.2 导入

# 全库导入
dimp SYSDBA/'xxx'@host:5236 \
  FILE=/dm/bak/dexp/full_20261105.dmp \
  LOG=/dm/bak/dexp/imp_full.log \
  FULL=Y

# 按用户导入(可改 Schema 名)
dimp SYSDBA/'xxx'@host:5236 \
  FILE=/dm/bak/dexp/test.dmp LOG=/dm/bak/dexp/imp.log \
  OWNER=TEST REMAP_SCHEMA=TEST:TEST_NEW

# 按表导入(表已存在时的处理)
dimp SYSDBA/'xxx'@host:5236 \
  FILE=/dm/bak/dexp/orders.dmp \
  TABLES=TEST.ORDERS \
  TABLE_EXISTS_ACTION=APPEND     # APPEND / TRUNCATE / REPLACE / SKIP

# 改表空间
dimp ... REMAP_TABLESPACE=TEST_TS:NEW_TS
参数 说明
REMAP_SCHEMA=A:B 把 A 导入到 B
REMAP_TABLESPACE=A:B 表空间重映射
TABLE_EXISTS_ACTION APPEND(追加)/ TRUNCATE(清空再导)/ REPLACE(删表重建)/ SKIP
IGNORE=Y 忽略创建错误

TABLE_EXISTS_ACTION 默认是 SKIP,表已存在时静默跳过,日志里只有一行提示。做增量导入时如果没显式设 APPEND,会发现「导了但没数据」。

12.3 dmfldr 文本装载

# 控制文件 t1.ctl
cat > /dm/data/t1.ctl <<'EOF'
LOAD DATA
INFILE '/dm/data/t1.txt'
INTO TABLE TEST.T1
FIELDS '|'
(ID, NAME, AMOUNT, CREATED_AT)
EOF

# 执行
dmfldr SYSDBA/'xxx'@host:5236 CONTROL='/dm/data/t1.ctl' MODE='IN'

dmfldr 是达梦最快的批量装载工具(比 INSERT 快一个数量级),适合初始化导入。MODE='IN' 装载,MODE='OUT' 卸载。


13. 归档与 PITR

13.1 开启归档

-- 1) 改 dm.ini 打开归档开关
SP_SET_PARA_VALUE(2, 'ARCH_INI', 1);

-- 2) 建归档配置文件 dmarch.ini
# /dm/data/DAMENG/dmarch.ini
[ARCHIVE_LOCAL1]
ARCH_TYPE     = LOCAL
ARCH_DEST     = /dm/arch
ARCH_FILE_SIZE = 1024
ARCH_SPACE_LIMIT = 102400
-- 3) 切到 MOUNT 状态开归档
ALTER DATABASE MOUNT;
ALTER DATABASE ARCHIVELOG;
ALTER DATABASE OPEN;

-- 4) 确认
SELECT ARCH_MODE FROM V$DATABASE;   -- Y 表示已开启
SELECT * FROM V$ARCHIVED_LOG ORDER BY FIRST_TIME DESC;
SELECT * FROM V$ARCH_STATUS;
# 5) 重启使 dmarch.ini 生效(部分版本需要)
systemctl restart DmServiceDMSERVER

13.2 归档管理

-- 查看归档配置
SELECT * FROM V$ARCHIVE_DEST;

-- 查看归档日志
SELECT RECID, NAME, FIRST_TIME, NEXT_TIME, ROUND(BYTES/1024/1024,2) mb, STATUS
FROM V$ARCHIVED_LOG ORDER BY RECID DESC LIMIT 20;

-- 手工切换联机日志(触发归档)
ALTER DATABASE ARCHIVELOG CURRENT;

-- 手工归档
ALTER DATABASE ARCHIVE LOG ALL;

-- 删除已备份的归档(释放空间)
ALTER DATABASE DELETE ARCHIVELOG BEFORE '2026-10-29';

13.3 PITR 流程

# 1) 确认归档连续
#    查看 V$ARCHIVED_LOG,时间不能有断档

# 2) 停库
systemctl stop DmServiceDMSERVER

# 3) 还原最近的基准备份
dmrman CTLSTMT="RESTORE DATABASE '/dm/data/DAMENG/dm.ini' FROM BACKUPSET '/dm/bak/full/full_20261105'"

# 4) 恢复到故障前时间点
dmrman CTLSTMT="RECOVER DATABASE '/dm/data/DAMENG/dm.ini' WITH ARCHIVEDIR '/dm/arch' UNTIL TIME '2026-11-05 09:29:00'"

# 5) 启动并验证
systemctl start DmServiceDMSERVER
-- 验证
SELECT STATUS$ FROM V$INSTANCE;
SELECT COUNT(*) FROM TEST.ORDERS WHERE CREATED_AT > TO_TIMESTAMP('2026-11-05 09:00:00');

恢复到时间点后,数据库会重置日志序列。这意味着恢复点之后的归档无法再用,且原库不能直接切回。恢复前一定要保留原数据目录(mv DAMENG DAMENG.bak),否则救错了没有退路。


14. 数据守护(Data Watch)

14.1 架构

主库(Primary)──实时同步──> 备库(Standby)
   │                          │
   └── dmwatcher ─────────────┘
              │
         dmmonitor(人工/自动切换)
模式 说明 RPO
实时主备 主库提交前等备库确认 0
实时归档 主库提交后异步发送 秒级
异步备库 定时同步 分钟级

14.2 配置主库

# 主库 dm.ini 关键项
INSTANCE_NAME = DM1
PORT_NUM = 5236
MAL_INI = 1
ARCH_INI = 1
ALTER_MODE_STATUS = 0
ENABLE_OFFLINE_TS = 2
# 主库 dmmal.ini(MAL 网络配置,主备必须一致)
[MAL_INST1]
MAL_INST_NAME = DM1
MAL_HOST = 10.0.0.11
MAL_PORT = 5237
MAL_INST_HOST = 10.0.0.11
MAL_INST_PORT = 5236

[MAL_INST2]
MAL_INST_NAME = DM2
MAL_HOST = 10.0.0.12
MAL_PORT = 5237
MAL_INST_HOST = 10.0.0.12
MAL_INST_PORT = 5236
# 主库 dmarch.ini(实时归档到备库)
[ARCHIVE_REALTIME]
ARCH_TYPE = REALTIME
ARCH_DEST = DM2

[ARCHIVE_LOCAL1]
ARCH_TYPE = LOCAL
ARCH_DEST = /dm/arch
ARCH_FILE_SIZE = 1024
ARCH_SPACE_LIMIT = 102400
-- 设为主库模式
ALTER DATABASE MOUNT;
ALTER DATABASE PRIMARY;
ALTER DATABASE OPEN;

14.3 配置备库

备库先用 dminit 初始化,再用 dmrman 从主库全量还原:

# 1) 备库初始化
dminit PATH=/dm/data DB_NAME=DAMENG INSTANCE_NAME=DM2 PORT_NUM=5236

# 2) 停备库,从主库还原
dmrman CTLSTMT="RESTORE DATABASE '/dm/data/DAMENG/dm.ini' FROM BACKUPSET '/dm/bak/full/full_20261105'"
dmrman CTLSTMT="RECOVER DATABASE '/dm/data/DAMENG/dm.ini' FROM BACKUPSET '/dm/bak/full/full_20261105'"
-- 3) 设为备库模式
ALTER DATABASE MOUNT;
ALTER DATABASE STANDBY;
ALTER DATABASE OPEN;
# 4) 备库 dmarch.ini
[ARCHIVE_REALTIME]
ARCH_TYPE = REALTIME
ARCH_DEST = DM1

[ARCHIVE_LOCAL1]
ARCH_TYPE = LOCAL
ARCH_DEST = /dm/arch

14.4 dmwatcher 与 dmmonitor

# dmwatcher.ini(主备都要配,内容相同)
[GRP1]
DW_TYPE = GLOBAL
DW_MODE = AUTO
DW_ERROR_TIME = 10
INSTANCE_NAME = DM1
INSTANCE_HOST = 10.0.0.11
PORT_NUM = 5237
INST_OK = TRUE
ISTATUS = OPEN
IMODE = PRIMARY
RSTAT = VALID
RTYPE = REALTIME
...

[GRP2]
DW_TYPE = GLOBAL
DW_MODE = AUTO
DW_ERROR_TIME = 10
INSTANCE_NAME = DM2
INSTANCE_HOST = 10.0.0.12
PORT_NUM = 5237
...
# dmmonitor.ini(监视器,可独立机器)
MON_DW_CONFIRM = 1
MON_LOG_PATH = /dm/log/monitor
MON_LOG_INTERVAL = 60
MON_LOG_FILE_SIZE = 32
MON_LOG_SPACE_LIMIT = 2048

[GRP1]
MON_INST_OGUID = 453331
MON_DW_IP = 10.0.0.11:5237
MON_DW_IP = 10.0.0.12:5237
# 注册并启动
dm_service_installer.sh -t dmwatcher -dm_ini /dm/data/DAMENG/dmwatcher.ini -p DM1
dm_service_installer.sh -t dmmonitor -dm_ini /dm/data/DAMENG/dmmonitor.ini -p MON

systemctl start DmWatcherServiceDM1
systemctl start DmMonitorServiceMON
# 监视器命令
dmmonitor /dm/data/DAMENG/dmmonitor.ini

MON> show global info           # 全局状态
MON> show database              # 各库状态
MON> show switchover            # 可切换列表
MON> switchover GRP1.DM2        # 主备切换
MON> takeover GRP1.DM2          # 强制接管(主机故障)
MON> show monitor               # 监视器自身状态

switchover 与 takeover 的区别:

  • switchover:主库正常,先追平再切,不丢数据,可回切;
  • takeover:主库不可用,强制备库接管,可能丢数据,原主恢复后必须重建。 生产能用 switchover 就别用 takeover。

14.5 守护状态检查

-- 主库看备库同步
SELECT * FROM V$RLOG;
SELECT * FROM V$ARCH_STATUS;

-- 主备 LSN 对比(主库)
SELECT CUR_LSN FROM V$RLOG;
-- 备库
SELECT CUR_LSN FROM V$RLOG;
-- 两者接近 = 同步正常
# dmwatcher 日志
tail -f /dm/data/DAMENG/dmwatcher.log

# 监视器状态
MON> show database
# 关注 IMODE(PRIMARY/STANDBY)、ISTATUS(OPEN)、RSTAT(VALID)

15. DMDSC 共享存储集群

15.1 架构

        共享存储(SAN / 分布式块存储)
              │
   ┌──────────┼──────────┐
   │          │          │
节点1        节点2       节点3
dmserver    dmserver    dmserver
dmcss       dmcss       dmcss
   │          │          │
   └──── dmcssm(监视器)─┘
组件 作用
dmasm 自动存储管理(可选,管理裸设备)
dmcss 集群同步服务,维护节点成员关系
dmcssm 集群监视器,人工控制
dmserver 数据库实例(多节点同时读写)

15.2 dmcssm 常用命令

$DM_HOME/bin/dmcssm /dm/data/DAMENG/dmcssm.ini

CSSM> show cluster          # 集群状态
CSSM> show cluster all      # 详细
CSSM> show ep               # 节点列表
CSSM> ep startup            # 启动所有节点
CSSM> ep stop               # 停止所有节点
CSSM> ep halt 1             # 停止节点 1
CSSM> ep switch 1           # 切换控制节点

15.3 关键点

项 要求
共享存储 必须支持并发写(SAN / 分布式块存储),不能用 NFS
心跳网络 独立网卡,万兆优先
仲裁盘 必须有,防脑裂
License 必须集群版
数据文件 全部放共享存储
联机日志 每节点独立(不共享)

DMDSC 不是「主备」而是「多活」:所有节点同时读写同一份数据,靠全局锁(GLS)协调。这带来两个运维要求:① 时钟必须严格同步(偏差 > 1 秒会报错);② 任一节点故障后必须用 dmcssm 确认状态再操作,不能直接重启。


16. 日志与监控

16.1 日志位置

日志 路径 内容
运行日志 $DM_HOME/log/dm_DMSERVER_YYYYMM.log 启动、错误、慢 SQL
归档日志 /dm/arch 归档文件
联机日志 $DM_HOME/data/DAMENG/DAMENG01.log 当前 redo
备份日志 dmrman 输出的 .log 备份记录
审计日志 表 V$AUDITRECORDS 需开审计
守护日志 dmwatcher.log 主备同步
# 实时跟踪
tail -f /opt/dmdbms/log/dm_DMSERVER_202611.log

# 找错误
grep -E '\[ERROR\]|\[FATAL\]' dm_DMSERVER_202611.log | tail -100

# 按时间
awk '/2026-11-05 09:2/,/2026-11-05 09:3/' dm_DMSERVER_202611.log

# 统计错误类型
grep -oE '\[ERROR\][^,]*' dm_DMSERVER_202611.log | sort | uniq -c | sort -rn | head -20

16.2 SQL 日志

-- 开启 SQL 日志(记录所有 SQL)
SP_SET_PARA_VALUE(1, 'SVR_LOG', 1);
SP_SET_PARA_VALUE(1, 'SVR_LOG_NAME', 'SLOG_ALL');

-- 慢 SQL 阈值(毫秒)
SP_SET_PARA_VALUE(1, 'SQL_TRACE_MASK', 1);

-- 日志文件在 $DM_HOME/log/svr.log
# sqllog.ini 精细配置
[SLOG_ALL]
FILE_PATH = /dm/log
SWITCH_MODE = S
SWITCH_LIMIT = 128
ASYNC_FLUSH = N
FILE_NUM = 10
ITEMS = 0
SQL_TRACE_MASK = 1
MIN_EXEC_TIME = 1000

16.3 监控视图

-- 实例运行状态
SELECT * FROM V$INSTANCE;

-- 会话
SELECT SESS_ID, USER_NAME, STATE, CLNT_IP, CREATE_TIME, LEFT(SQL_TEXT,80)
FROM V$SESSIONS WHERE STATE <> 'IDLE';

-- 内存
SELECT * FROM V$MEM_POOL ORDER BY TOTAL_SIZE DESC;
SELECT NAME, TOTAL_SIZE/1024/1024 AS mb, N_PAGES FROM V$BUFFERPOOL;

-- 事务
SELECT * FROM V$TRX WHERE STATUS = 'ACTIVE';

-- 锁
SELECT * FROM V$LOCK WHERE BLOCKED = 1;

-- 等待
SELECT * FROM V$TRXWAIT;

-- 系统信息
SELECT * FROM V$SYSTEMINFO;

-- 线程
SELECT * FROM V$THREADS;

16.4 监控平台

工具 说明
DM 管理工具(Manager) 图形化客户端,含监控面板
DM 性能监视器 独立工具 dmsmonitor
DEM(达梦企业管理器) Web 版集中监控,需单独部署
Prometheus 通过 dm_exporter 采集
Zabbix 官方模板可用

17. 性能诊断

17.1 执行计划

-- 查看计划
EXPLAIN SELECT * FROM TEST.ORDERS WHERE USER_ID = 1001;

-- 带统计信息(需实际执行)
EXPLAIN ANALYZE SELECT ...;

-- 计划缓存
SELECT * FROM V$CACHEPLN WHERE SQL_ID = '<sql_id>';
SELECT * FROM V$SQL_PLAN WHERE SQL_ID = '<sql_id>';

-- 清缓存
SP_CLEAR_PLAN_CACHE();
SP_CLEAR_PLAN_CACHE('TEST');

执行计划危险信号:

现象 含义 处置
SSCAN(全表扫描)+ 大表 无索引或索引失效 补索引 / 收集统计信息
估算行数 与实际差 10 倍 统计信息过期 DBMS_STATS.GATHER_TABLE_STATS
HASH JOIN 的构建表很大 驱动表选错 收集统计信息 / 用 HINT
SORT 落盘 排序缓冲不足 调大 SORT_BUF_SIZE
BLKUP(回表)次数多 索引选择性差 用覆盖索引
-- HINT 用法
SELECT /*+ INDEX(T IDX_ORDERS_USER) */ * FROM TEST.ORDERS T WHERE USER_ID = 1001;
SELECT /*+ FULL(T) */ * FROM TEST.ORDERS T;
SELECT /*+ HASH_JOIN(T1 T2) */ ...;

17.2 TOP SQL

-- 按执行时间排序(需开启监控)
SELECT SQL_ID, SQL_TEXT, EXEC_TIME/1000 AS ms,
       EXEC_NUM, LOGIC_READ, PHYSICAL_READ, PARSE_TIME/1000 AS parse_ms
FROM V$SQL
ORDER BY EXEC_TIME DESC LIMIT 20;

-- 按逻辑读排序(找 IO 大户)
SELECT SQL_ID, LEFT(SQL_TEXT,100), LOGIC_READ, PHYSICAL_READ, EXEC_NUM
FROM V$SQL ORDER BY LOGIC_READ DESC LIMIT 20;

-- 历史 SQL
SELECT * FROM V$SQL_HISTORY WHERE EXEC_TIME > 1000000 ORDER BY EXEC_TIME DESC LIMIT 20;

17.3 锁与阻塞

-- 当前锁等待
SELECT L.TRX_ID AS WAIT_TRX, L.TABLE_ID, L.ROW_IDX,
       S.SESS_ID AS WAIT_SESS, S.SQL_TEXT AS WAIT_SQL,
       LT.TRX_ID AS BLOCK_TRX
FROM V$LOCK L
JOIN V$SESSIONS S ON L.TRX_ID = S.TRX_ID
LEFT JOIN V$LOCK LT ON L.TABLE_ID = LT.TABLE_ID AND L.ROW_IDX = LT.ROW_IDX AND LT.BLOCKED = 0
WHERE L.BLOCKED = 1;

-- 阻塞源
SELECT * FROM V$TRXWAIT;

-- 长事务
SELECT TRX_ID, SESS_ID, STATUS, DATEDIFF(SS, START_TIME, SYSDATE) AS sec
FROM V$TRX WHERE STATUS = 'ACTIVE' ORDER BY sec DESC;

-- 杀会话
SP_CLOSE_SESSION(<sess_id>);

17.4 AWR 报告

DM8 提供 DBMS_WORKLOAD_REPOSITORY 包:

-- 建快照
DBMS_WORKLOAD_REPOSITORY.CREATE_SNAPSHOT();

-- 查看快照
SELECT * FROM DBA_HIST_SNAPSHOT ORDER BY SNAP_ID DESC LIMIT 10;

-- 生成 HTML 报告(两个快照之间)
DBMS_WORKLOAD_REPOSITORY.AWR_REPORT_HTML(1, 2, '/tmp/awr_1_2.html');

-- 生成文本报告
DBMS_WORKLOAD_REPOSITORY.AWR_REPORT_TEXT(1, 2, '/tmp/awr_1_2.txt');

-- 修改快照策略(每 60 分钟,保留 7 天)
DBMS_WORKLOAD_REPOSITORY.MODIFY_SNAPSHOT_SETTINGS(10080, 60);

AWR 依赖 ENABLE_MONITOR=1 且已开启统计收集。如果 DBA_HIST_SNAPSHOT 为空,先确认 DM_INI 里的 ENABLE_MONITOR 和历史收集参数。

17.5 内存诊断

-- 内存池分布
SELECT NAME, TOTAL_SIZE/1024/1024 AS mb, N_PAGES, PAGE_SIZE/1024 AS page_kb
FROM V$MEM_POOL ORDER BY TOTAL_SIZE DESC;

-- 缓冲池命中率
SELECT NAME, N_PAGES, N_FREE_PAGES, N_LOGIC_READS, N_PHYS_READS,
       ROUND((1 - N_PHYS_READS/NULLIF(N_LOGIC_READS,0))*100, 2) AS hit_pct
FROM V$BUFFERPOOL;

-- 排序/哈希缓冲使用
SELECT * FROM V$SORT_HISTORY ORDER BY SORT_TIME DESC LIMIT 10;

缓冲池命中率低于 95% 说明 BUFFER 不够或存在大量全表扫描。先看命中率,再决定加内存还是加索引——很多「内存不足」其实是缺索引导致的物理读暴涨。


18. 空间与容量管理

18.1 空间统计

-- 库级大小
SELECT ROUND(SUM(BYTES)/1024/1024/1024, 2) AS total_gb FROM DBA_DATA_FILES;

-- 按 Schema
SELECT OWNER, ROUND(SUM(BYTES)/1024/1024, 2) AS mb
FROM DBA_SEGMENTS GROUP BY OWNER ORDER BY mb DESC;

-- 按表
SELECT OWNER, SEGMENT_NAME, SEGMENT_TYPE,
       ROUND(BYTES/1024/1024/1024, 2) AS gb,
       BLOCKS
FROM DBA_SEGMENTS
WHERE SEGMENT_TYPE = 'TABLE'
ORDER BY BYTES DESC LIMIT 20;

-- 单表(含索引)
SELECT SEGMENT_NAME, ROUND(SUM(BYTES)/1024/1024, 2) AS total_mb
FROM DBA_SEGMENTS
WHERE SEGMENT_NAME = 'ORDERS' AND OWNER = 'TEST'
GROUP BY SEGMENT_NAME;

-- 表空间使用率(见 9.1 的完整 SQL)

18.2 回收空间

-- 1) 删数据(分批)
DELETE FROM TEST.LOGS WHERE LOG_TIME < TO_DATE('2026-01-01','YYYY-MM-DD');
-- 大表建议按分区 DROP,不要 DELETE

-- 2) 收缩表(释放高水位以上空间)
ALTER TABLE TEST.LOGS SHRINK SPACE;
ALTER TABLE TEST.LOGS SHRINK SPACE CASCADE;   -- 连带索引

-- 3) 重建表(彻底整理)
--    新建表 → INSERT SELECT → RENAME

-- 4) 缩小数据文件
ALTER DATABASE DATAFILE '/dm/data/DAMENG/test_ts02.dbf' RESIZE 1024;
操作 锁 释放空间 说明
DELETE 行锁 否 标记删除
TRUNCATE TABLE 表锁 是(高水位下降) 快,不可回滚
DROP PARTITION 分区锁 是 大表首选
SHRINK SPACE 表锁 是 在线整理
RESIZE 数据文件 文件锁 是 需要先 shrink

18.3 容量告警阈值

对象 警告 严重 处置
表空间 80% 90% 加数据文件 / 开自动扩展
TEMP 80% 95% 扩 TEMP_SIZE
归档目录 80% 90% 备份后删除旧归档
数据盘 80% 90% 扩容 / 迁移
联机日志 — 循环覆盖 保证 RLOG_BUF_SIZE 与日志文件数

19. 升级与迁移

19.1 小版本升级

# 1) 停库
systemctl stop DmServiceDMSERVER

# 2) 备份(数据 + dm.ini + License)
cp -r /dm/data/DAMENG /dm/data/DAMENG.bak_$(date +%F)
cp /opt/dmdbms/bin/dm.key /dm/bak/dm.key.bak

# 3) 安装新版本到新目录(不要覆盖旧目录)
./DMInstall.bin -q /tmp/dm_install_new.xml

# 4) 用新版本的 dmserver 启动旧数据目录(DM 支持小版本原地升级)
/opt/dmdbms_new/bin/dmserver /dm/data/DAMENG/dm.ini

# 5) 验证后切换服务指向

达梦的小版本升级是兼容的(8.1.2.x → 8.1.3.x 可直接用新二进制启动旧库),但大版本不能(DM7 → DM8 必须用 DTS 迁移)。升级前必须备份,且要保留旧版本的 bin 目录以便回退。

19.2 从 Oracle 迁移

差异 Oracle DM8 处置
数据字典 ALL_TABLES DBA_TABLES(兼容视图存在) 部分可直接用
ROWNUM 支持 支持(COMPATIBLE_MODE=1) —
DUAL 有 有 —
NVL 支持 支持 —
序列 SEQ.NEXTVAL 同 —
存储过程 PL/SQL DM SQL/PL(高度兼容) 大部分可直接迁
BFILE 支持 部分支持 需改造
分区自动新增 INTERVAL 不支持 必须改造为定时任务
ROWID 支持 支持但语义不同 不建议依赖
# 用 DTS 工具迁移(图形化)
$DM_HOME/tool/dts

# 或用 dexp/dimp(Oracle 侧先导出为 DM 兼容格式)

19.3 从 MySQL 迁移

差异 MySQL DM8 处置
反引号 支持 COMPATIBLE_MODE=2 支持 建议改双引号
LIMIT 支持 COMPATIBLE_MODE=2 支持 —
AUTO_INCREMENT 支持 用 IDENTITY 建表改造
存储引擎 InnoDB 无此概念 去掉 ENGINE=
字符集 utf8mb4 UTF-8(CHARSET=1) 建库时定
大小写 依赖 OS CASE_SENSITIVE 建库时定,不可改

20. 高频故障速查

20.1 起不来

报错 原因 处置
创建共享内存失败 上次 kill -9 残留 ipcs -m 找到并 ipcrm -m <id>
dm.ini 不存在 路径写错 检查 dmserver 后的绝对路径
License 过期 dm.key 到期 换 License
端口被占用 5236 被占 ss -lntp | grep 5236
需要更多恢复 恢复了但没 RECOVER 执行 dmrman RECOVER
数据文件损坏 磁盘故障 从备份还原 + RECOVER
# 共享内存残留的标准处理
ipcs -m | grep dmdba
ipcrm -m <shmid>
ipcs -s | grep dmdba
ipcrm -s <semid>

20.2 连不上

# 1) 进程在不在
ps -ef | grep dmserver | grep -v grep

# 2) 端口通不通
ss -lntp | grep 5236
telnet 10.0.0.11 5236

# 3) 防火墙
firewall-cmd --list-ports
systemctl status firewalld

# 4) 会话数满
-- 会话数是否打满
SELECT COUNT(*) FROM V$SESSIONS;
SELECT PARA_NAME, PARA_VALUE FROM V$DM_INI WHERE PARA_NAME = 'MAX_SESSIONS';

20.3 归档异常

-- 归档是否开启
SELECT ARCH_MODE FROM V$DATABASE;

-- 归档配置
SELECT * FROM V$ARCHIVE_DEST;

-- 归档状态
SELECT * FROM V$ARCH_STATUS;

-- 归档日志
SELECT * FROM V$ARCHIVED_LOG ORDER BY RECID DESC LIMIT 10;
现象 原因 处置
ARCH_MODE=N 没开归档 MOUNT → ARCHIVELOG → OPEN
归档目录不增长 dmarch.ini 没配 / ARCH_INI=0 检查配置并重启
归档空间满 ARCH_SPACE_LIMIT 到了 备份后删旧归档,或调大限制

20.4 主备不同步

# 1) 看监视器
MON> show database

# 2) 看 dmwatcher 日志
tail -100 /dm/data/DAMENG/dmwatcher.log

# 3) 看 LSN 差距
# 主库 SELECT CUR_LSN FROM V$RLOG;
# 备库 SELECT CUR_LSN FROM V$RLOG;
状态 含义 处置
RSTAT = VALID 同步正常 —
RSTAT = INVALID 归档失效 检查 MAL 网络、归档目录
ISTATUS = MOUNT 备库未 OPEN ALTER DATABASE OPEN
IMODE = STANDBY 但主库也是 STANDBY 没有主库 手工指定 PRIMARY

20.5 性能突然下降

① 是否有统计信息过期?   DBA_TABLES.LAST_ANALYZED
② 是否有锁等待?         V$LOCK / V$TRXWAIT
③ 是否有大事务?         V$TRX 按 START_TIME 排序
④ 缓冲池命中率?         V$BUFFERPOOL
⑤ 是否有全表扫描?       V$SQL 按 LOGIC_READ 排序 + EXPLAIN
⑥ 磁盘 IO?              iostat -x 1
⑦ 归档是否卡住?         V$ARCH_STATUS

21. 危险命令与避坑清单

# 命令 风险 防护
1 kill -9 dmserver 共享内存残留,起不来 用 SHUTDOWN IMMEDIATE
2 DROP USER ... CASCADE 删用户全部对象,不进回收站 先查 DBA_TABLES 数量
3 DROP TABLESPACE ... INCLUDING DATAFILES 删数据文件,不可恢复 确认无业务表;先备份
4 TRUNCATE TABLE 不可回滚 确认表名;生产禁用直连
5 dminit 重复初始化同一目录 覆盖 dm.ini,实例错乱 初始化前 ls 确认目录为空
6 改 COMPATIBLE_MODE 解析行为变化,SQL 可能报错 测试库回归,重启前备份
7 改 BUFFER 过大 OOM,实例被 kill 不超过物理内存 60%
8 ALTER DATABASE ARCHIVELOG 忘记 OPEN 库停在 MOUNT,业务全断 三步一起执行
9 takeover 代替 switchover 丢数据,原主需重建 主库还活着就用 switchover
10 单机 License 配数据守护 dmwatcher 启动失败 确认 License 类型

变更前五步

  1. 备份:BACKUP DATABASE FULL,确认 V$BACKUPSET 有记录;
  2. 确认状态:SELECT STATUS$ FROM V$INSTANCE,别在 MOUNT 状态做业务操作;
  3. 备份配置:cp dm.ini dm.ini.bak.$(date +%F);
  4. 确认 License:集群操作前 SELECT * FROM V$LICENSE;
  5. 留痕:记录变更前后 V$SESSIONS、V$TRX、表空间使用率快照。

22. 附录:一键巡检脚本

#!/usr/bin/env bash
# dm_health_check.sh —— 一分钟巡检
# 用法:su - dmdba 后执行 ./dm_health_check.sh
set -uo pipefail

export DM_HOME=${DM_HOME:-/opt/dmdbms}
PORT=${PORT:-5236}
USER_PWD=${USER_PWD:-SYSDBA/SYSDBA}

Q() { "$DM_HOME/bin/disql" -S "$USER_PWD"@127.0.0.1:"$PORT" -e "$1" 2>/dev/null; }

echo "==================== 达梦 DM 巡检 $(date '+%F %T') ===================="

echo -e "\n--- 1. 实例状态 ---"
Q "SELECT INSTANCE_NAME, STATUS\$, MODE\$, ARCH_MODE FROM V\$INSTANCE;"

echo -e "\n--- 2. 版本 ---"
Q "SELECT BUILD_VERSION, BUILD_TIME FROM V\$INSTANCE;"

echo -e "\n--- 3. 会话数 / 上限 ---"
Q "SELECT (SELECT COUNT(*) FROM V\$SESSIONS) AS cur_sess,
          (SELECT PARA_VALUE FROM V\$DM_INI WHERE PARA_NAME='MAX_SESSIONS') AS max_sess
   FROM DUAL;"

echo -e "\n--- 4. 活跃会话 TOP10 ---"
Q "SELECT SESS_ID, USER_NAME, STATE, CLNT_IP, LEFT(SQL_TEXT,60)
   FROM V\$SESSIONS WHERE STATE <> 'IDLE' ORDER BY CREATE_TIME LIMIT 10;"

echo -e "\n--- 5. 长事务(>5min)---"
Q "SELECT TRX_ID, SESS_ID, DATEDIFF(SS, START_TIME, SYSDATE) AS sec
   FROM V\$TRX WHERE STATUS='ACTIVE'
   ORDER BY sec DESC LIMIT 10;"

echo -e "\n--- 6. 锁等待 ---"
Q "SELECT * FROM V\$TRXWAIT;"

echo -e "\n--- 7. 表空间使用率(>80% 关注)---"
Q "SELECT T.TABLESPACE_NAME,
          ROUND(SUM(D.BYTES)/1024/1024,0) AS total_mb,
          ROUND((SUM(D.BYTES)-NVL(SUM(F.BYTES),0))/1024/1024,0) AS used_mb
   FROM DBA_DATA_FILES D
   JOIN DBA_TABLESPACES T ON D.TABLESPACE_NAME=T.TABLESPACE_NAME
   LEFT JOIN DBA_FREE_SPACE F ON D.FILE_ID=F.FILE_ID
   GROUP BY T.TABLESPACE_NAME ORDER BY used_mb DESC;"

echo -e "\n--- 8. 缓冲池命中率 ---"
Q "SELECT NAME, ROUND((1-N_PHYS_READS/NULLIF(N_LOGIC_READS,0))*100,2) AS hit_pct
   FROM V\$BUFFERPOOL;"

echo -e "\n--- 9. 归档状态 ---"
Q "SELECT ARCH_TYPE, ARCH_DEST, ARCH_STATUS FROM V\$ARCHIVE_DEST;"

echo -e "\n--- 10. 最近备份 ---"
Q "SELECT BACKUP_NAME, BACKUP_TYPE, ROUND(BACKUP_SIZE/1024/1024,0) AS mb, END_TIME
   FROM V\$BACKUPSET ORDER BY END_TIME DESC LIMIT 5;"

echo -e "\n--- 11. TOP SQL(按执行时间)---"
Q "SELECT LEFT(SQL_TEXT,60), EXEC_TIME/1000 AS ms, EXEC_NUM
   FROM V\$SQL ORDER BY EXEC_TIME DESC LIMIT 5;"

echo -e "\n--- 12. 磁盘 / 归档目录 ---"
df -h "$DM_HOME/data" /dm/arch /dm/bak 2>/dev/null | awk 'NR==1 || /[0-9]%/{print "  "$0}'

echo -e "\n--- 13. 日志 ERROR 计数(近 500 行)---"
LOG=$(ls -t "$DM_HOME"/log/dm_DMSERVER_*.log 2>/dev/null | head -1)
[ -n "$LOG" ] && printf "  %-60s %s\n" "$LOG" "$(tail -500 "$LOG" | grep -c '\[ERROR\]')"

echo -e "\n--- 14. dmap 服务 ---"
systemctl is-active DmAPService 2>/dev/null || echo "  DmAPService 未运行(备份会失败)"

echo -e "\n==================== 巡检结束 ===================="

速查表

需求 命令
启停 systemctl start/stop DmServiceDMSERVER
状态 SELECT STATUS$ FROM V$INSTANCE
参数 SP_SET_PARA_VALUE(1,'k',v)
建库 dminit PATH=...
备份 BACKUP DATABASE FULL BACKUPSET '...'
恢复 dmrman → RESTORE + RECOVER
逻辑导出 dexp ... FULL=Y
逻辑导入 dimp ... FULL=Y
开归档 MOUNT → ARCHIVELOG → OPEN
主备切换 dmmonitor → switchover
锁等待 V$LOCK / V$TRXWAIT
TOP SQL V$SQL
AWR DBMS_WORKLOAD_REPOSITORY.AWR_REPORT_HTML
会话 V$SESSIONS
杀会话 SP_CLOSE_SESSION(sess_id)

最后一句:达梦是「最像 Oracle 的国产库」,运维心智可以大量复用 Oracle 经验。但有三个必须记住的差异:① 统计信息不自动收集;② 分区不自动新增;③ 备份必须先起 DmAPService。这三条是国产化替代项目里最高频的翻车点。

达梦 DM 常用运维指令手册 - 知识库 - 起航社区