注册
【开源分享】dmtop:把达梦数据库性能诊断链压缩到一个终端
专栏/技术分享/ 文章详情 /

【开源分享】dmtop:把达梦数据库性能诊断链压缩到一个终端

孙莹 2026/08/21 259 2 0
摘要

项目名称: dmtop
项目定位: 达梦数据库本机实时性能诊断 TUI
支持平台: Linux amd64 / arm64
开源协议: MIT License
Gitee: https://gitee.com/sun-ying1119/dmtop
GitHub: https://github.com/greatfinish/dmtop

本文功能以当前 main 分支为准;可执行文件版本和支持内容以 Releases 页面说明为准。

数据库“变慢”只是一个现象,不是一个诊断结论。

面对突发性能问题,DBA 通常先登录数据库服务器,用 topvmstatiostatsar 判断 CPU、内存、磁盘和网络是否异常;再进入数据库查询 V$SESSIONSV$SYSSTATV$TRXV$TRXWAITV$SQL_STAT。如果发现达梦进程中的某个线程 CPU 很高,还要继续把 Linux TID 映射到数据库 SID,再从会话追到 SQL、存储过程内部语句、执行计划或阻塞者。

每一个命令都有价值,真正困难的是这些证据分散在不同终端、不同采样时刻和不同统计口径中。问题持续时间越短,DBA 越容易在切换命令和拼接字段的过程中错过现场。

dmtop 想做的事情很明确:

不建设另一套监控平台,而是把当前故障需要的 Linux 和 DM8 证据放进同一个终端,让 DBA 更快地从“数据库慢”走到“哪台设备、哪个线程、哪个会话、哪条 SQL 或哪条阻塞链”。


为什么要做一个达梦数据库 TUI 工具

传统诊断链路很完整,但不够集中

一次常见的现场排查可能从下面这些命令开始:

top -H -p $(pgrep -o dmserver) vmstat 1 iostat -x 1 sar -n DEV 1

随后进入数据库继续查询:

SELECT * FROM V$SESSIONS; SELECT * FROM V$SYSSTAT; SELECT * FROM V$TRX; SELECT * FROM V$TRXWAIT; SELECT * FROM V$SQL_STAT;

这些数据还需要人工关联:

Linux dm_sql_thd
        ↓ TID
V$SESSIONS.THRD_ID
        ↓ SID / SQL_TEXT_ID
当前 SQL、完整 SQL、执行计划
        ↓ TRX_ID / WAIT_FOR_ID
阻塞者、等待者、锁对象

问题不在于 DBA 不会使用这些命令,而在于故障现场需要更快地建立关联。操作系统看到的是线程和设备,数据库看到的是会话、事务和 SQL;只有把两部分放在同一采样窗口中,才能形成可靠的因果判断。

平台化监控和现场诊断解决的是不同问题

DEM、Exporter/Prometheus、性能快照和 AWR 类报告适合长期监控、趋势分析、告警和历史回溯。它们解决的是“过去一段时间发生了什么”。

dmtop 解决的是另一个问题:

我已经登录故障主机,现在最应该先看什么?

因此,dmtop 有意保持轻量:

  • 不部署 Agent;
  • 不启动常驻服务;
  • 不依赖 disql
  • 不要求目标机器安装 Go 工具链;
  • 不长期保存监控数据;
  • 发布版使用单个 Linux 可执行文件。

这也是选择 TUI 的原因。它保留了命令行工具启动快、资源占用低、适合 SSH 终端的特点,同时能持续刷新、排序、选中和下钻,不必把每次查询结果复制到另一个窗口再分析。


dmtop 要解决的核心问题

dmtop 将 Linux /proc 与 DM8 动态视图组织成同一份实时证据快照,集中回答六个问题:

  1. 当前瓶颈在 CPU、内存、磁盘还是网络?
  2. 数据库当前是高吞吐、重 SQL、硬解析还是锁等待?
  3. 哪个数据库会话对应 Linux 中的高 CPU 线程?
  4. 客户端提交的是存储过程时,内部真正执行的 SQL 是什么?
  5. 哪个会话阻塞了哪个会话,根阻塞者和锁对象是谁?
  6. 当前数字是采样区间增量、累计值,还是暂时无法可靠获取?

它的诊断链可以概括为:

Linux /proc                         DM8 dynamic views
CPU / memory / disk / network       V$SESSIONS / V$SYSSTAT / V$TRXWAIT / ...
              |                                  |
              +----------------+-----------------+
                               |
                               v
                       Interval Snapshot
                               |
              +----------------+----------------+
              |                |                |
              v                v                v
             OS               DB             PROCESS
                                                |
                                  +-------------+-------------+
                                  |                           |
                                  v                           v
                              SQL Detail                  LOCK CHAIN

一个主界面包含哪些功能

dmtopmain.png

DATABASE:确认诊断目标

首行展示实例模式、状态、数据库名、实例名、数据库运行时间、实例数量和归档状态。

在单机、主备和多环境并存的系统中,先确认当前连接的是哪个实例,比任何性能指标都重要。诊断对象一旦看错,后续数字再精确也没有意义。

OPERATING SYSTEM PERFORMANCE:判断主机瓶颈

OS 区域直接读取本机 /proc,展示:

  • CPU user、system、idle、iowait;
  • 1/5/15 分钟 load average;
  • 运行和阻塞进程数;
  • 内存 used、free、cached 与 Swap;
  • 最热磁盘的 util、await、RIO/WIO、RMB/WMB;
  • 非 loopback 网卡的 RX/TX。

这部分先回答“数据库慢是不是主机资源造成的”。例如,CPU 很低但磁盘 util 和 await 同时升高,排查方向就不应该继续停留在 SQL CPU 上。

DATABASE PERFORMANCE:判断数据库负载类型

DB 区域采用相邻采样计算速率,主要包含:

指标 诊断意义
sessions / active / idle 当前连接与活动会话规模
rw trx / trx waits 有 DML、持锁或阻塞证据的事务,以及实时事务等待关系
STMT/s 数据库全局语句吞吐,能够反映存储过程内部静态 SQL
CURSOR/s 当前采样区间可见游标执行速率,不冒充全局 QPS
TPS / UCPS 事务与用户提交速率
LIO / PRD / PWR / REDO 逻辑读、物理读写和 Redo 压力
PARSE / HARD / HARD% / PERR 解析、硬解析比例和解析错误
PLANHIT 计划缓存辅助证据;口径矛盾时降级为 N/A
SYNC / LOCKMS/s / DEADLOCK 单次提交同步延迟、区间锁等待时间和新增死锁

速率指标在首帧显示 warming up,数据源失败显示 N/A,当前状态不适用显示 -dmtop 不会把未知数据伪装成精确的零。

PROCESS:把 SID、TID、事务和 SQL 放到同一行

PROCESS 最多显示 20 个用户会话,按当前采样区间 CPU 从高到低排列。主要字段包括:

SID  TID  %CPU  AGE  STATE  USERNAME  SQL_TEXT_ID
CLNT_IP  CLNT_HOST  APPNAME  SQL_TEXT

TID 来自 V$SESSIONS.THRD_ID,可以直接和下面的 Linux 结果对应:

top -H -p $(pgrep -o dmserver)

选中会话按 Enter,可以查看三层 SQL:

  • V$SESSIONS.SQL_TEXT:客户端提交的 SQL 或 CALL
  • CUR_SQLSTR:当前正在执行的内部 SQL;
  • SF_GET_SESSION_SQL(SID):会话完整 SQL。

x 输入 SQL_TEXT_ID,可以继续查看完整 SQL 和执行计划。

SQL RT、SQL CUM 和 SQL PATTERN:区分当前、累计和模板

dmtop 将 SQL 证据拆成三种语义:

  • SQL RT:相邻采样区间的 EXEC/sLIO/sLIO/EXHARD/sCPU%,用于定位当前负载;
  • SQL CUM:游标创建以来的累计资源消耗,用于发现长期重 SQL;
  • SQL PATTERN:把数字和字符串常量归一化成 ?,用于发现未使用绑定变量的 SQL 模板。

例如:

SELECT * FROM T_ORDER WHERE ORDER_ID = 10001; SELECT * FROM T_ORDER WHERE ORDER_ID = 10002;

会归并为:

SELECT * FROM T_ORDER WHERE ORDER_ID = ?

模板面板展示 VARIANTS/sHARD/sEXEC/sCPU%,并关联 USER、APPNAME、CLNT_HOST 与 CLNT_IP。

LOCK CHAIN:直接展示谁堵住了谁

dmtop 基于 V$TRXWAIT.WAIT_FOR_ID 展开阻塞关系:

ROOT BLOCKER --[TID/T_LOCK_TEST]--> WAITER

多级阻塞按照 ROOT BLOCKER -> WAITER 展示,并关联双方 SID、TID、用户、锁类型、锁模式、对象和等待时长。DDL 锁可以显示为 OBJECT/X。没有阻塞时,LOCK CHAIN 不占主界面空间。

确认异常会话确实需要处理时,可以按 k 输入数据库 SID。工具会重新展示会话证据并要求二次确认,然后调用 SP_CLOSE_SESSION(SID)。这里使用的是数据库 SID,不是 Linux TID;不建议直接对达梦线程执行 kill -9


故障案例一:一条 SQL 占满一个 CPU 核

现象

业务响应变慢,但服务器总 CPU 只有 12% 左右。单看总 CPU,容易误判为“CPU 不高”。

在 dmtop 中怎么查

第一步,看 OS 区域:

cpus: 8
CPU user: 12.5%

8 核主机上,一个线程占满单核时,整机 CPU 大约就是 100% / 8 = 12.5%。总 CPU 不高,不代表没有单线程瓶颈。

第二步,看 PROCESS:

TID 2249281  %CPU 100.0  ACTIVE  AGE 2m

红色 %CPU 表明该达梦线程已经接近占满一个核心。SID、TID、用户、客户端和 SQL 已经在同一行,不再需要人工映射。

第三步,按 Enter 查看:

CLIENT_SQL   CALL RIS.P_CPU_BURN(...)
CURRENT_SQL  SELECT SUM(...) FROM ...
FULL_SQL     CALL RIS.P_CPU_BURN(...)

客户端看到的是存储过程调用,真正消耗 CPU 的是 CURRENT_SQL。必要时按 x 查看完整 SQL 和执行计划。

结论如何形成

OS 单核压力
  + PROCESS TID 100% CPU
  + ACTIVE AGE 持续增长
  + CUR_SQLSTR 指向计算型 SQL
  = CPU 型长 SQL

故障案例二:存储过程内部出现高频 SQL

现象

数据库逻辑读快速增长,但 SQL RT 中看不到相同数量的游标执行。业务可能把大量 SQL 封装在存储过程中,或者游标生命周期短于采样间隔。

在 dmtop 中怎么查

先比较 DB 区域的两个指标:

STMT/s    33000
CURSOR/s      0
LIO/s    198000

STMT/s 来自 V$SYSSTAT 的全局语句计数,可以观察存储过程内部语句;CURSOR/s 只表示采样区间可见游标的执行变化。两者差距很大时,dmtop 会提示:

INTERNAL SQL - STMT 33K/s, visible cursor executions 0/s

然后沿 PROCESS 找到高 CPU 或 ACTIVE 会话,按 Enter 查看 CUR_SQLSTR。如果相关游标能够跨采样保留,再进入 SQL RT 查看:

  • EXEC/s:执行频率;
  • LIO/s:总逻辑读压力;
  • LIO/EX:单次执行成本;
  • CPU%:对应会话线程 CPU。

如何区分两类问题

EXEC/s 高、LIO/EX 低  → 高频低成本 SQL,重点看调用次数
EXEC/s 低、LIO/EX 高  → 低频重 SQL,重点看执行计划和访问路径

故障案例三:应用没有使用绑定变量

现象

SQL 结构完全相同,只是条件中的数字或字符串不同。数据库需要反复解析新文本,CPU 消耗上升,计划缓存效率下降。

在 dmtop 中怎么查

先看 DB 区域:

PARSE/s  21000
HARD/s   20900
HARD%     99.5%
PERR/s       0

HARD/s 和接近 100% 的 HARD% 表明大部分解析都产生了硬解析。随后按 p 进入 SQL PATTERN:

VARIANTS/s  HARD/s  EXEC/s  USER  APPNAME  CLNT_HOST  SQL_PATTERN
20.9K       20.9K   ...     RIS   app.jar  cluster01  WHERE ID = ?

这组证据能够回答三个关键问题:

  1. 哪一类 SQL 文本在不断变化;
  2. 每秒产生多少文本变体和硬解析;
  3. 这些 SQL 来自哪个用户、程序和客户端主机。

当模板变体与全局硬解析风暴一致时,界面会给出 LITERAL SQL 提示。部分 DM8 版本的 plan total count 不能覆盖所有动态 SQL;如果 PLANHIT 与 HARD/s 明显矛盾,dmtop 会显示 N/A,避免用一个看似精确的数字误导判断。


故障案例四:长 SQL 到底是在计算,还是在等待

现象

某个 ACTIVE 会话持续很久。只看执行时间,无法判断它在使用 CPU、等待磁盘,还是被锁阻塞。

在 dmtop 中怎么查

持续超过阈值的请求会出现带证据的提示:

LONG SQL - SID ... TID ... age 2m, CPU 99.5%, WAIT -, CUR_SQL SELECT ...

诊断时组合判断:

证据 更可能的方向
%CPU 高、WAIT 为空 CPU 计算、函数运算、低效连接或大规模扫描
%CPU 低、磁盘 await 高、PRD/PWR 高 存储 I/O 等待
BLOCKER 非空、LOCK CHAIN 有记录 行锁或 DDL 锁等待
ACTIVE AGE 长但 CUR_SQLSTR 变化 一个长存储过程中依次执行多条内部 SQL

AGE 对 ACTIVE 会话表示当前请求年龄,即当前时间减 LAST_RECV_TIME。对于存储过程,它表示整个 CALL 的持续时间;内部单条语句要以实时 CUR_SQLSTR 为准。


故障案例五:长时间未提交事务

现象

应用执行了 DML 后没有及时提交,连接已经空闲,但事务仍保留修改或锁。普通会话列表容易把它看成一个没有负载的 IDLE 连接。

在 dmtop 中怎么查

DB 区域先观察:

rw trx 1

PROCESS 中会话显示:

STATE IDLE-TX  AGE >=12m  TRX_ID ...  DML_CNT 1  LOCK_CNT 3

持续达到阈值后会出现:

LONG TX - SID ... TX ... age >=12m, DML 1, locks 3, SQL UPDATE ...

这里的 >=12m 是 dmtop 连续观察到该事务的时间下限。DM8 当前动态视图没有提供可跨版本依赖的精确事务开始时间,因此工具不会把观测下限冒充真实事务年龄。

部分 DM8 版本会为只读空闲会话保留 V$TRX 行。dmtop 不会仅凭 TRX_ID != 0 就标记 IDLE-TX;只有存在 DML、持锁或参与阻塞链的证据时,才计入 rw trx 并展示事务年龄,避免把普通只读连接误报成长事务。


故障案例六:行锁和 DDL 锁阻塞

现象

一个会话持锁,后续会话依次等待。数据库表面上可能只有少数 ACTIVE 会话,但业务请求已经排队。

在 dmtop 中怎么查

先看 DB 区域:

trx waits 4
LOCKMS/s 2180

其中 trx waits 是当前捕获的事务等待关系;LOCKMS/sV$SYSSTAT 的区间锁等待毫秒率,两者不是同一个口径。

再看 LOCK CHAIN:

ROOT SID 101 TID 2001 APP
  --[TID/T_ORDER 35s]--> SID 102 TID 2002 APP
      --[TID/T_ORDER 12s]--> SID 103 TID 2003 APP

DDL 锁可能显示为:

--[OBJECT/X T_DDL_LOCK]-->

处理顺序应该是:

  1. 先确认根阻塞者,而不是先关闭最末端等待者;
  2. 核对根会话的 SID、TID、用户、客户端和 SQL;
  3. 判断它是在正常执行、空闲未提交,还是异常连接;
  4. 优先推动应用提交或回滚;
  5. 必须关闭时,按 k 重新核实目标 SID 并二次确认。

故障案例七:磁盘延迟和提交变慢

现象

业务提交耗时升高。问题可能来自数据库写入、Redo 刷盘、本地磁盘延迟,或者主备同步链路。

在 dmtop 中怎么查

先看 OS:

Disk util 95%
await 18ms
WIO/s 1200
WMB/s 85
iowait 22%

再看 DB:

PWR/s 1100
REDO/s 80M
SYNC 35ms

判断路径如下:

OS util/await 高 + DB PWR/REDO 高
    → 数据库写压力正在推高本地磁盘延迟

DB SYNC 高 + 本地 await 低
    → 继续检查日志路径、刷盘机制或同步主备链路

OS await 高 + DB PRD/PWR 低
    → 检查同机其他进程、其他文件系统或共享存储负载

当提交同步延迟达到诊断阈值时,dmtop 会给出 COMMIT LATENCY 提示,并同时展示 SYNC 与最热磁盘 await,提示不会脱离证据单独下结论。


为什么坚持在数据库主机本地运行

如果 dmtop 连接远程数据库,数据库指标来自远端实例,而 /proc 反映的却是本机,OS 和 DB 证据会发生错配。

因此,dmtop 的产品边界是本机快速诊断:把二进制放在达梦数据库服务器上运行,确保主机、线程、会话和 SQL 属于同一台机器。跨主机集中监控、长期趋势、告警、巡检报表和历史回放,应继续交给 DEM、Exporter/Prometheus 等持续监控体系。

dmtop 不是这些平台的替代品,而是 DBA 登录故障主机后用于快速收拢现场证据的第一把工具。


不同 DM8 版本如何避免“一列不兼容,整屏没数据”

不同 DM8 补丁版本的动态视图和字段可能存在差异。dmtop 启动时会通过:

V$DYNAMIC_TABLES
V$DYNAMIC_TABLE_COLUMNS

检测目标实例具备哪些视图和字段,再选择兼容查询。缺少可选字段时只对单项能力降级,不会因为一个字段不存在而让整个 PROCESS 区域消失。

监控 SQL 使用会话 ID 与 /*dmtop*/ 标记双重排除自身;连接池最多使用一条连接,每轮采样复用同一批结果派生摘要、PROCESS 与 SQL 指标,尽量降低诊断工具对被诊断系统的影响。


快速开始

发布版提供 Linux amd64 和 arm64 压缩包。它不依赖 disql、Go 工具链或外部 Agent。

下载地址:

安装发布包:

tar -xzf dmtop-v0.2.2-linux-amd64.tar.gz cd dmtop-v0.2.2-linux-amd64 chmod +x dmtop sudo install -m 0755 dmtop /usr/local/bin/dmtop

默认连接本机 5236 端口:

dmtop SYSDBA

指定非默认端口:

dmtop SYSDBA@127.0.0.1:5237

程序会隐藏密码输入,不需要把密码写进命令行、shell history 或进程列表。

常用交互键:

按键 操作
m 返回 PROCESS
s / S 打开 SQL RT / SQL CUM
p / 5 打开 SQL PATTERN
Enter 查看选中会话或 SQL 的详细证据
x 输入 SQL_TEXT_ID,查看完整 SQL 和执行计划
k 输入数据库 SID,核实并关闭会话
e 查看参数、规模和环境信息
f 冻结或恢复刷新
h 查看帮助
q 返回或退出

开源与反馈

dmtop 使用 MIT License 开源。达梦原生 Go 驱动由用户从自己的 DM 安装目录或官方下载包单独提供,不包含在项目 MIT 授权范围内;下载预编译发布包的用户不需要额外安装驱动。

不同 DM8 版本、补丁和业务负载会带来不同的诊断现场。欢迎提交 Issue、字段兼容信息和真实故障案例,让这个工具逐步覆盖更多达梦数据库排障路径。

dmtop 不追求把所有数据库管理功能塞进一个终端。它只想把性能故障中最容易分散的证据提前关联好,让 DBA 少切换几个窗口、少拼接几段 SQL,更快地找到下一步应该检查和处理的对象。

评论
后发表回复

作者

文章

阅读量

获赞

扫一扫
联系客服