适用版本:达梦数据库(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)还原出的全量语句 |
日志文件离线分析 | 大规模统计排序、图表输出、"单条不慢但总量大"的佐证 |
选用建议:
V$LONG_EXEC_SQLS;V$SQL_HISTORY;SVR_LOG 后用 DMLOG 分析。该视图用于快速定位执行时间超过阈值的慢 SQL 语句,默认显示最近 1000 条执行时间超过 1000 毫秒的 SQL。
配套视图 V$SYSTEM_LONG_EXEC_SQLS 则记录服务器(实例)启动以来执行时间最长的 SQL 语句(默认 300 条),两者配合可分别回答"最近谁慢"和"历史上谁最慢"。
| 字段 | 说明 |
|---|---|
SESS_ID |
会话 ID |
SQL_ID |
SQL 语句标识 |
SQL_TEXT |
SQL 文本 |
EXEC_TIME |
执行时间(毫秒) |
FINISH_TIME |
结束时间 |
| 参数 | 说明 |
|---|---|
ENABLE_MONITOR |
监控总开关。必须设为 1 才能启用视图记录功能;为 0 时本视图(以及 V$SQL_HISTORY 等监控视图)均无数据 |
LONG_EXEC_SQLS_CNT |
控制 V$LONG_EXEC_SQLS 的记录条数上限,取值范围 1000 ~ 1000000,默认 1000,超出后覆盖最旧的记录 |
⚠️ 排查时若视图迟迟无数据,请先确认
ENABLE_MONITOR的取值。
通过系统函数/存储过程可临时调整"慢"的判定阈值:
-- 将阈值临时设置为 5 秒(单位:毫秒)
CALL SP_SET_LONG_TIME(5000);
-- 查看当前阈值
SELECT SF_GET_LONG_TIME();
注意事项:
SQLLOG(即 SVR_LOG 日志)体系,在 sqllog.ini 中配置 MIN_EXEC_TIME,详见本文第五章。-- 查询最近记录的慢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;
V$SQL_HISTORY 或 DMLOG 做完整分析;记录最近执行的所有 SQL 的历史信息(不限于慢 SQL),适合做全面的历史回溯、事务关联分析和阻塞排查。同样在 ENABLE_MONITOR=1 时启用采集。
| 字段 | 说明 |
|---|---|
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等字段查看,各版本字段细节以官方手册为准。
| 参数 | 说明 |
|---|---|
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()刷新即可生效,无需重启(如需彻底生效可重启实例)。
-- ① 按执行时间降序查询历史慢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;
定位阻塞源头时,推荐"三级链路":
V$TRXWAIT(可获知被阻塞会话及它等待的会话/事务);V$SESSIONS(用户名、状态、当前正在执行的 SQL_TEXT、所属 TRX_ID 等);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分段"的明细查询。
TIME_USED 单位为微秒,与 V$LONG_EXEC_SQLS.EXEC_TIME 的毫秒不同,对比/换算时务必除以 1000;SQL_HISTORY_CNT;| 对比项 | 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 是达梦官方提供的轻量级 SQL 日志分析工具,用于解析数据库的 SQL 跟踪日志,统计执行时间最长和调用频次最高的 SQL 语句,并以图表和 Excel 形式输出,辅助性能优化。
log_commit 表 → 在数据库中完成聚合、筛选、排序 → 输出 Excel 报表和图表。| 条件 | 说明 |
|---|---|
| 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 行,日志量过大时需切割分批分析 |
修改 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控制日志切换方式;各参数具体取值与版本相关,以官方手册为准。
# 后台分析库连接信息(测试环境!)
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
分析完成后,结果目录下通常包含:
\\ 代替 \;路径中不能有中文,否则报错;MIN_EXEC_TIME:控制记录的最小语句执行时间(毫秒),默认 0 表示不限制。若设置过大(如 10000),只有耗时超过 10 秒的 SQL 才会被记录,可能导致 DMLOG 分析结果中记录极少,请结合实际需要调整;SQL_TRACE_MASK:控制记录的 SQL 语句类型,设为 1 表示记录全部类型;sqllog.ini 后,需执行 SP_REFRESH_SVR_LOG_CONFIG() 使配置生效;log_commit 表会被覆盖:DMLOG 建表前会删除同名表,如有同名业务表请先备份;sqlpath。遇到"大事务执行上万条 SQL、总耗时长"的场景时,DMLOG 可作为辅助验证工具:
这从数据侧印证了"耗时不是单条 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—— 毫秒
文章
阅读量
获赞
