注册
达梦数据库慢SQL排查工具使用指南
专栏/技术分享/ 文章详情 /

达梦数据库慢SQL排查工具使用指南

何处惹尘埃 2026/09/18 368 0 0
摘要

适用版本:达梦数据库(DM8 及以上)
涉及工具:V$LONG_EXEC_SQLS / V$SYSTEM_LONG_EXEC_SQLS 动态性能视图、V$SQL_HISTORY 动态性能视图、DMLOG SQL 日志分析工具
一句话速览:日常用视图实时定位慢SQL,用历史视图做事务/阻塞回溯,日志量大或需要全量统计时用 DMLOG 做深度分析,三类工具互为补充。


一、工具概览与选型

工具 记录范围 数据来源 典型场景
V$LONG_EXEC_SQLS 仅记录执行时间超过阈值的慢SQL(默认最近 1000 条) 运行期监控内存 快速定位当前/近期"哪条 SQL 慢"
V$SYSTEM_LONG_EXEC_SQLS 自实例启动以来累计执行时间最长的SQL(默认 300 条) 运行期监控内存 查看历史最耗时 SQL 榜单
V$SQL_HISTORY 所有已执行 SQL(全量,默认 10000 条) 运行期监控内存 历史回溯、事务/会话/阻塞关联分析
DMLOG 由 SQL 日志(SVR_LOG)还原出的全量语句 日志文件离线分析 大规模统计排序、图表输出、"单条不慢但总量大"的佐证

选用建议:

  • 快速回答"哪条 SQL 慢" → 用 V$LONG_EXEC_SQLS;
  • 需要结合事务 ID、会话信息做深度排查(如定位阻塞事务)→ 用 V$SQL_HISTORY;
  • 需要全量语句的耗时/频次统计、或 SQL 量巨大 → 开启 SVR_LOG 后用 DMLOG 分析。

二、V$LONG_EXEC_SQLS 视图

2.1 功能定位

该视图用于快速定位执行时间超过阈值的慢 SQL 语句,默认显示最近 1000 条执行时间超过 1000 毫秒的 SQL。

配套视图 V$SYSTEM_LONG_EXEC_SQLS 则记录服务器(实例)启动以来执行时间最长的 SQL 语句(默认 300 条),两者配合可分别回答"最近谁慢"和"历史上谁最慢"。

2.2 关键字段

字段 说明
SESS_ID 会话 ID
SQL_ID SQL 语句标识
SQL_TEXT SQL 文本
EXEC_TIME 执行时间(毫秒)
FINISH_TIME 结束时间

2.3 相关配置参数

参数 说明
ENABLE_MONITOR 监控总开关。必须设为 1 才能启用视图记录功能;为 0 时本视图(以及 V$SQL_HISTORY 等监控视图)均无数据
LONG_EXEC_SQLS_CNT 控制 V$LONG_EXEC_SQLS 的记录条数上限,取值范围 1000 ~ 1000000,默认 1000,超出后覆盖最旧的记录

⚠️ 排查时若视图迟迟无数据,请先确认 ENABLE_MONITOR 的取值。

2.4 慢SQL时间阈值设置

通过系统函数/存储过程可临时调整"慢"的判定阈值:

-- 将阈值临时设置为 5 秒(单位:毫秒) CALL SP_SET_LONG_TIME(5000); -- 查看当前阈值 SELECT SF_GET_LONG_TIME();

注意事项:

  • 阈值单位为毫秒,默认 1000;
  • 上述方式修改的是运行期参数,实例重启后失效(恢复默认值);
  • 如需持久化,需走 SQLLOG(即 SVR_LOG 日志)体系,在 sqllog.ini 中配置 MIN_EXEC_TIME,详见本文第五章。

2.5 使用示例

-- 查询最近记录的慢SQL,按执行时间降序,取前 20 条 SELECT TOP 20 SESS_ID, SQL_ID, EXEC_TIME, FINISH_TIME, SQL_TEXT FROM V$LONG_EXEC_SQLS ORDER BY EXEC_TIME DESC; -- 查看服务器启动以来最耗时的SQL SELECT TOP 50 SESS_ID, SQL_ID, EXEC_TIME, FINISH_TIME, SQL_TEXT FROM V$SYSTEM_LONG_EXEC_SQLS ORDER BY EXEC_TIME DESC;

2.6 使用注意与局限

  • 该视图只记录超过阈值的 SQL,不记录全部执行历史;阈值以内的 SQL 不会出现在此视图中;
  • 在排查"单条 SQL 不慢、但总量大"的场景时,本视图可能只记录很少甚至没有记录,需结合 V$SQL_HISTORY 或 DMLOG 做完整分析;
  • 视图数据基于运行期监控内存,实例重启后清空。

三、V$SQL_HISTORY 视图

3.1 功能定位

记录最近执行的所有 SQL 的历史信息(不限于慢 SQL),适合做全面的历史回溯、事务关联分析和阻塞排查。同样在 ENABLE_MONITOR=1 时启用采集。

3.2 关键字段

字段 说明
SEQ_NO 序列号(可按其排序还原执行先后顺序)
SQL_ID SQL 标识
SESS_ID 会话 ID
TRX_ID 事务 ID(这是本视图相对慢SQL视图最大的增量信息)
TOP_SQL_TEXT 顶层 SQL 文本(含参数替换后的实际内容)
TIME_USED 执行时间(微秒,注意与毫秒的单位差异)
START_TIME 开始时间
N_LOGIC_READ 逻辑读次数
N_PHY_READ 物理读次数(物理读偏高常与缺索引、缓冲池命中率低相关)
AFFECTED_ROWS 影响行数
EXEC_ID 执行 ID

补充说明:TOP_SQL_TEXT 记录的是顶层入口语句的文本;当存在嵌套执行(如存储过程、触发器内部触发的语句)时,实际执行语句可结合 SQL_TEXT 等字段查看,各版本字段细节以官方手册为准。

3.3 配置参数

参数 说明
SQL_HISTORY_CNT 控制 V$SQL_HISTORY 最大记录数,取值范围 1000 ~ 100000,默认 10000

修改示例:

-- 调大历史记录容量,避免高并发/长事务场景下记录被过早淘汰 SP_SET_PARA_VALUE(1, 'SQL_HISTORY_CNT', 50000); CALL SP_REFRESH_SVR_LOG_CONFIG();

修改后执行 SP_REFRESH_SVR_LOG_CONFIG() 刷新即可生效,无需重启(如需彻底生效可重启实例)。

3.4 使用示例

-- ① 按执行时间降序查询历史慢SQL(注意 TIME_USED 微秒 → 毫秒换算) SELECT TOP 20 SQL_ID, SESS_ID, TRX_ID, TIME_USED / 1000 AS TIME_MS, TOP_SQL_TEXT FROM V$SQL_HISTORY ORDER BY TIME_USED DESC; -- ② 按事务ID查询某事务执行过的所有SQL(还原事务内语句序列) SELECT SQL_ID, SESS_ID, TRX_ID, TIME_USED / 1000 AS TIME_MS, TOP_SQL_TEXT FROM V$SQL_HISTORY WHERE TRX_ID = 6669843700 ORDER BY START_TIME; -- ③ 按会话ID查询历史SQL SELECT * FROM V$SQL_HISTORY WHERE SESS_ID = 1234; -- ④ 用逻辑读/物理读辅助判断SQL开销 SELECT TOP 20 SQL_ID, TIME_USED/1000 AS TIME_MS, N_LOGIC_READ, N_PHY_READ, AFFECTED_ROWS, TOP_SQL_TEXT FROM V$SQL_HISTORY ORDER BY N_LOGIC_READ DESC;

3.5 阻塞排查进阶用法

定位阻塞源头时,推荐"三级链路":

  1. 查等待关系:V$TRXWAIT(可获知被阻塞会话及它等待的会话/事务);
  2. 查会话详情:V$SESSIONS(用户名、状态、当前正在执行的 SQL_TEXT、所属 TRX_ID 等);
  3. 反查事务语句序列:用上一步拿到的阻塞事务 TRX_ID 在 V$SQL_HISTORY 中还原该事务执行过的全部 SQL,找出长时间持锁的语句。
-- ① 查看当前等待关系,确认阻塞者(等待者会话ID、等待的会话/事务ID) SELECT * FROM V$TRXWAIT; -- ② 查看相关会话信息(用户名、状态、当前SQL、事务ID) SELECT SESS_ID, USER_NAME, TRX_ID, SQL_TEXT FROM V$SESSIONS WHERE SESS_ID IN (/* 被阻塞会话ID, 阻塞会话ID */); -- ③ 将阻塞事务执行过的SQL按开始时间拼接/排序输出 SELECT LISTAGG(TOP_SQL_TEXT, CHAR(10)) FROM V$SQL_HISTORY sh, V$SESSIONS block_sess WHERE sh.TRX_ID = block_sess.trx_id AND sh.SESS_ID = block_sess.sess_id AND sh.TRX_ID = 6669843700; -- 或者按时间顺序明细查看,便于逐条分析持锁语句 SELECT SEQ_NO, START_TIME, TIME_USED/1000 AS TIME_MS, TOP_SQL_TEXT FROM V$SQL_HISTORY WHERE TRX_ID = 6669843700 ORDER BY START_TIME;

💡 LISTAGG 拼接结果受字符串长度上限影响,语句较多时可改为"按 SEQ_NO / START_TIME 分段"的明细查询。

3.6 注意事项

  • 单位差异:TIME_USED 单位为微秒,与 V$LONG_EXEC_SQLS.EXEC_TIME 的毫秒不同,对比/换算时务必除以 1000;
  • 容量限制:默认仅保留 10000 条,高并发或长事务场景下可能查不到完整结果,建议结合实际调大 SQL_HISTORY_CNT;
  • 重启清空:数据库(实例)重启后,该视图数据清空。

四、V$ LONG_EXEC_SQLS 与 V$ SQL_HISTORY 对比

对比项 V$LONG_EXEC_SQLS V$SQL_HISTORY
记录范围 仅超过阈值的慢 SQL 所有执行过的 SQL(全量)
默认容量 1000 条(LONG_EXEC_SQLS_CNT,1000~1000000) 10000 条(SQL_HISTORY_CNT,1000~100000)
时间字段/单位 EXEC_TIME / 毫秒 TIME_USED / 微秒
是否含事务 ID 否 是(TRX_ID)
语句文本 SQL_TEXT TOP_SQL_TEXT(含参数替换后内容)
适用场景 快速定位当前/近期慢 SQL 历史回溯,事务/会话/阻塞关联分析
采集前提 ENABLE_MONITOR=1 ENABLE_MONITOR=1

五、DMLOG 工具使用说明

5.1 工具简介与工作原理

DMLOG 是达梦官方提供的轻量级 SQL 日志分析工具,用于解析数据库的 SQL 跟踪日志,统计执行时间最长和调用频次最高的 SQL 语句,并以图表和 Excel 形式输出,辅助性能优化。

  • 基于 Java 开发,不提供 SQL 优化建议,只做数据统计与展示;
  • 工作原理:读取本地 SQL 日志文件 → 批量写入后台达梦库的 log_commit 表 → 在数据库中完成聚合、筛选、排序 → 输出 Excel 报表和图表。

5.2 使用条件

条件 说明
Java 环境 需预先安装 Java 1.8 及以上,支持 Linux 与 Windows
后台库 PAGE_SIZE 必须为 32K,否则会报错
SVR_LOG 必须开启(默认 0 关闭),通过 SP_SET_PARA_VALUE(1,'SVR_LOG',1) 开启
运行环境 严禁连接生产环境分析:DMLOG 运行时会向分析库的 log_commit 表写入大量数据,必须在测试环境分析生产环境导出的日志文件
Excel 行数限制 单个 sheet 最多 65536 行,日志量过大时需切割分批分析

5.3 配置步骤

第一步:开启 SQL 日志跟踪

修改 sqllog.ini 配置文件,指定日志路径与记录规则:

FILE_PATH = /dmdata/sqllog SQL_TRACE_MASK = 1 # 1 表示记录全部类型的SQL MIN_EXEC_TIME = 0 # 最小记录阈值(毫秒),默认0表示不限制

随后在数据库中执行:

-- 使 sqllog.ini 配置生效 CALL SP_REFRESH_SVR_LOG_CONFIG(); -- 开启 SQL 日志记录 CALL SP_SET_PARA_VALUE(1, 'SVR_LOG', 1);

稍后即可在 FILE_PATH 指定目录下看到 dmsql_实例名_日期_时间.log 格式的日志文件生成。

补充:sqllog.ini 中还常用 FILE_NUM(日志文件个数)与 FILE_SIZE(单个文件大小)控制日志保留容量,SWITCH_MODE 控制日志切换方式;各参数具体取值与版本相关,以官方手册为准。

第二步:修改 dmlog.properties 配置文件

# 后台分析库连接信息(测试环境!)
ip=127.0.0.1
port=5236
username=SYSDBA
password=Dameng123

# 分析模式:0=根据日志新生成数据,1=根据已存在数据生成结果(免重复解析,直接出报表)
use_result=0

# SQL日志文件夹绝对路径(Windows 使用双反斜杠)
sqlpath=/dm8/log/

# 分析多少毫秒以上的SQL语句,0 表示无限制
time=0

# 是否生成 excel 统计结果
if_excel=1

# 后台分析表名
tab_name=log_commit

第三步:执行分析

# 常规启动(Windows 带界面可直接运行) java -jar Dmlog_DM_8.18.jar # Linux 无图形界面环境:增加 headless 参数(-D 需放在 -jar 之前) java -Djava.awt.headless=true -jar Dmlog_DM_8.18.jar

5.4 输出结果

分析完成后,结果目录下通常包含:

  • Excel 报表(xls):按执行时间排序、按执行次数排序各一份;
  • 文本文件(txt):报错 SQL 与超长 SQL 的独立清单;
  • 图表(html):ECharts 散点图、QPS 折线图、平均耗时统计图。

5.5 注意事项与常见坑

  • dmlog.properties 中的日志路径:Windows 下使用双反斜杠 \\ 代替 \;路径中不能有中文,否则报错;
  • sqllog.ini 中的 MIN_EXEC_TIME:控制记录的最小语句执行时间(毫秒),默认 0 表示不限制。若设置过大(如 10000),只有耗时超过 10 秒的 SQL 才会被记录,可能导致 DMLOG 分析结果中记录极少,请结合实际需要调整;
  • sqllog.ini 中的 SQL_TRACE_MASK:控制记录的 SQL 语句类型,设为 1 表示记录全部类型;
  • 每次修改 sqllog.ini 后,需执行 SP_REFRESH_SVR_LOG_CONFIG() 使配置生效;
  • log_commit 表会被覆盖:DMLOG 建表前会删除同名表,如有同名业务表请先备份;
  • 分析用的日志应保持原始格式,不要手工改动后放入 sqlpath。

5.6 在"大事务逐条 SQL 累计耗时"场景中的用法

遇到"大事务执行上万条 SQL、总耗时长"的场景时,DMLOG 可作为辅助验证工具:

  1. 将产生该事务的完整 SQL 日志导出;
  2. 在测试环境用 DMLOG 分析;
  3. 观察结论:通常可以看到绝大多数 SQL 的单条执行时间排序处于中等偏低水平,但执行次数排序中该事务的 SQL 占据极大比重。

这从数据侧印证了"耗时不是单条 SQL 慢,而是大量逐条交互累积"的判断,为业务逻辑批量合并优化方向提供数据支撑(如将逐条 INSERT/UPDATE 改写为批量语句,减少与数据库的往返次数)。


六、综合排查思路速览

现象/需求 推荐路径
明确"某时间段有慢SQL",想快速定位 V$LONG_EXEC_SQLS 按 EXEC_TIME 降序;必要时先用 SP_SET_LONG_TIME 调低阈值
应用侧只报"慢",视图里查不到 用 V$SQL_HISTORY 按时间窗 / SESS_ID / TRX_ID 反查
单条不慢、总量大(批量逐条执行) 开启 SVR_LOG → DMLOG 按"执行次数"排序,找高频小语句
会话卡死、疑似锁等待/阻塞 V$TRXWAIT → V$SESSIONS → V$SQL_HISTORY(按 TRX_ID 还原语句序列)
视图没有任何数据 检查 ENABLE_MONITOR 是否为 1;确认实例是否刚重启(运行期视图重启即清空)
需要持久化的慢SQL审计/阈值 走 SVR_LOG + sqllog.ini.MIN_EXEC_TIME,而非 SP_SET_LONG_TIME

附录:参数与容量速查表

参数 默认值 取值范围 作用 生效方式
ENABLE_MONITOR 1 0 / 1 监控总开关,决定上述监控视图是否采集 动态参数,即时生效
LONG_EXEC_SQLS_CNT 1000 1000 ~ 1000000 V$LONG_EXEC_SQLS 记录条数上限 动态参数
SQL_HISTORY_CNT 10000 1000 ~ 100000 V$SQL_HISTORY 记录条数上限 修改后 SP_REFRESH_SVR_LOG_CONFIG() 刷新
慢SQL阈值 1000 ms — SP_SET_LONG_TIME(毫秒) 临时修改;持久化用 sqllog.ini 的 MIN_EXEC_TIME 临时:即时生效、重启失效
SVR_LOG 0(关闭) 0 / 1 SQL 日志总开关,DMLOG 的前置条件 修改后 SP_REFRESH_SVR_LOG_CONFIG()
SQL_TRACE_MASK 0 0 / 1 / 组合值 记录 SQL 类型(1=全部) 修改 sqllog.ini 后刷新

附:单位提醒

三处时间口径易混淆,请务必区分:

  • V$LONG_EXEC_SQLS.EXEC_TIME —— 毫秒
  • V$SQL_HISTORY.TIME_USED —— 微秒(对比时除以 1000)
  • SP_SET_LONG_TIME() / MIN_EXEC_TIME —— 毫秒

评论
后发表回复

作者

文章

阅读量

获赞

扫一扫
联系客服