SQL 性能问题的排查往往离不开运行时日志。SQL 日志(sqllog)是达梦数据库记录所有 SQL 执行行为的"黑匣子",它完整记录了语句文本、执行时间、事务生命周期、锁等待、回滚页等关键信息。读懂并善用 sqllog,是 DBA 和开发人员定位慢 SQL、分析锁阻塞、追溯事务异常的核心技能。
学习目标:掌握 SQL 日志的开启与配置方法,能读懂事务、锁等待、回滚页等典型日志格式,并能结合日志工具在生产环境快速定位问题。
SQL 日志用于记录用户执行的 SQL 语句、绑定参数、执行耗时、错误信息以及事务事件等内容。它是一个纯文本文件,默认生成在 DM 安装目录的 log 子目录下,命名格式一般为:
dmsql_实例名[_模式名][_用户名][_日期_时间].log
一个 SQL 日志可能名为:dmsql_DMDB_DSC0_20260624_123456.log。
SQL 日志由 INI 参数 SVR_LOG 总开关控制,可以通过系统存储过程动态开启:
SP_SET_PARA_VALUE(1, 'SVR_LOG', 1); -- 开启 SQL 日志,按 sqllog.ini 配置记录
SVR_LOG 共有 4 种取值:
| 值 | 含义 |
|---|---|
| 0 | 关闭 SQL 日志功能(缺省值) |
| 1 | 打开,并按照 sqllog.ini 中的配置来记录 SQL 日志 |
| 2 | 打开,按文件中记录数量切换日志文件,日志记录为详细模式 |
| 3 | 打开,不切换日志文件,日志记录为简单模式,只记录时间和原始语句 |
在实际应用环境中,推荐设置为 1,配合
sqllog.ini精细化控制日志粒度,避免日志量过大占用磁盘。
当 SVR_LOG = 1 时,数据库会读取 sqllog.ini 配置文件来决定记录哪些内容、如何切换文件、占用多大空间。
如果在服务器运行过程中修改了 sqllog.ini,我们需要手动调用以下存储过程,动态刷新配置,新的配置才能生效:
SP_REFRESH_SVR_LOG_CONFIG();
可以通过以下两种动态视图查询当前配置:
-- 查询 sqllog.ini 文件配置
SELECT * FROM V$DM_SQLLOG_INI;
-- 查询内存中生效的 SQL 日志配置
SELECT * FROM V$DM_SQLLOG_CONFIG;
sqllog.ini 分为全局配置区和模式配置区:
全局配置项(BUF_TOTAL_SIZE、BUF_SIZE、BUF_KEEP_CNT 等)对全部模式生效;
模式配置区可针对不同模式单独设置,优先级:模式配置 > 全局配置 > 缺省值。
以下是一套常见的 sqllog 配置样例:
BUF_TOTAL_SIZE = 10240 # SQL日志BUFFER总上限,单位KB
BUF_SIZE = 1024 # 单块BUFFER大小,单位KB
BUF_KEEP_CNT = 10 # 系统保留的缓存个数
[SLOG_ALL]
FILE_PATH = /dmdata/dmsqllog # 日志文件路径
SWITCH_MODE = 2 # 按文件大小切换
SWITCH_LIMIT = 512 # 单文件512MB切换
ASYNC_FLUSH = 1 # 开启异步刷盘
FILE_NUM = 200 # 最多保留200个文件
SQL_TRACE_MASK = 2:3:4:5:6:7:8:9:10:11:12:13:14:15:16:17:22:23:24:25:26:27:28:29
MIN_EXEC_TIME = 100 # 只记录执行≥100ms的SQL
USER_MODE = 2 # 用户黑名单模式
USERS = # 黑名单用户列表
我们不可能将所有sqllog日志写在一个log文件中,通过SWITCH_MODE,我们可以配置文件的切换规则
| 值 | 模式 | 对应SWITCH_LIMIT 含义 |
|---|---|---|
| 0 | 不切换(不推荐) | — |
| 1 | 按文件中记录数量切换 | 单文件 SQL 记录条数阈值,缺省为 100000 |
| 2 | 按文件大小切换(默认) | 单文件大小阈值,单位 MB,缺省为 128 |
| 3 | 按时间间隔切换 | 切换间隔,单位分钟,缺省为 60 |
这是最核心的配置项,用冒号分隔的位号控制记录哪些类型的语句和信息。常用位号含义:
| 位号 | 说明 |
|---|---|
| 1 | 全部记录(等同于同时设置 4~31) |
| 2 | DML 类型相关语句(等同于同时设置 4~10) |
| 3 | DDL 类型相关语句(等同于同时设置 11~17) |
| 4 | UPDATE 类型语句(更新) |
| 5 | DELETE 类型语句(删除) |
| 6 | INSERT 类型语句(插入) |
| 7 | SELECT 类型语句(查询) |
| 8 | COMMIT 类型语句(提交) |
| 9 | ROLLBACK 类型语句(回滚) |
| 10 | CALL 类型语句(过程调用) |
| 11 | BACKUP 类型语句(备份) |
| 12 | RESTORE 类型语句(恢复) |
| 13 | 创建对象操作(CREATE DDL) |
| 14 | 修改对象操作(ALTER DDL) |
| 15 | 删除对象操作(DROP DDL) |
| 16 | 授权操作(GRANT DDL) |
| 17 | 回收操作(REVOKE DDL) |
| 22 | 记录绑定参数的行数 |
| 23 | 记录存在错误的语句(语法错误,语义分析错误等) |
| 24 | 记录执行语句 |
| 25 | 记录执行语句、执行语句的时间、语句的影响行数(只有增删改查有行数,其它语句无行数) |
| 26 | 记录执行语句的时间、语句的影响行数(只有增删改查有行数,其它语句无行数)。25 和 26 二者只能选择其一,同时存在时只有 25 有效 |
| 27 | 记录原始语句(服务器从客户端收到的未加分析的语句) |
| 28 | 记录参数信息,包括参数的序号、数据类型和值 |
| 29 | 记录事务相关事件,包括锁类型、锁等待时间等 |
| 30 | 记录 XA 事务 |
| 31 | 记录数据库登录操作,包括登录成功、登录失败、退出登录 |
实际应用场景建议按需配置掩码,例如开启 25 + 29 即可覆盖大部分性能排查与锁分析场景,避免日志量爆炸。
详细参考《DM8系统管理员手册》2.1.1.4.1 sqllog.ini 配置项
一条客户端连接从建立到就绪,日志中一般会以四个阶段体现:
服务端响应登录并创建会话,会话地址生成,线程号显示为 -1;
分配线程并初始化事务编号,事务 ID 为 0;
完成用户认证,记录客户端名称与用户信息;
进入语句地址分配环节,未执行 SQL 时 stmt 为 NULL。
事务的开启、提交、回滚都会在日志中留下明确标记:
2026-03-17 09:36:33.389 (EP[0] sess:0x7f749f000a78 thrd:13652 user:****** trxid:209831439 stmt:NULL appname: ip:::ffff:172.16.xxx.xxx) TRX: START
2026-03-17 09:36:33.472 (EP[0] sess:0x7f749f000a78 thrd:13652 user:****** trxid:209831440 stmt:NULL appname: ip:::ffff:172.16.xxx.xxx) TRX: COMMIT
2026-03-17 09:36:33.407 (EP[0] sess:0x7f749f000a78 thrd:13652 user:****** trxid:209831439 stmt:NULL appname: ip:::ffff:172.16.xxx.xxx) TRX: ROLLBACK
各字段含义:
| 字段内容 | 字段名 | 说明 |
|---|---|---|
| 2026-03-17 09:36:33.389 | 时间戳 | 日志生成的精确时间,精度到毫秒,用于判定操作先后顺序 |
| EP[0] | 执行池编号(Execution Pool) | 达梦数据库后台执行线程池编号,EP[0] 代表 0 号默认执行池,数据库会通过不同 EP 分配任务 |
| sess:0x7f749f000a78 | 会话内存地址 | 数据库会话(连接)的内存唯一地址 |
| thrd:13652 | 服务端线程 ID | 数据库服务端处理当前会话的工作线程编号,一个会话固定绑定一个线程 |
| user:XXX | 数据库登录用户名 | / |
| trxid:209831439 | 事务 ID | 达梦内部全局唯一事务编号,一个事务对应一个独立 trxid,事务生命周期内 ID 不变 |
| stmt:NULL | SQL 语句对象地址 | 正在执行的 SQL 语句内存地址,NULL 表示当前会话无活跃执行的 SQL 语句 |
| appname: | 客户端应用名 | 客户端连接数据库时上报的应用程序名称,为空代表客户端未上报应用名 |
| ip:::ffff:172.xx.xxx.26 | 客户端 IP | 客户端主机地址,::ffff: 是IPv6 兼容 IPv4 格式,本质为内网 IPv4 地址 |
| TRX: START | 事务动作 | START:开启数据库事务 |
| TRX: ROLLBACK | 事务动作 | ROLLBACK:回滚当前事务,撤销事务内所有操作 |
| TRX: COMMIT | 事务动作 | COMMIT:提交当前事务,固化事务内所有操作 |
一条完整的 SQL 执行会包含以下典型标记:
[SEL] / [ORA]:普通查询 / Oracle 兼容模式执行,后面紧跟 SQL 文本。此外还有如[UPD]、[INS]、[DEL]的操作符,分别对应更新、插入、删除。Load para: N rows:加载绑定变量,N 为参数组数。PARAMS(SEQNO, TYPE, DATA):绑定变量明细,包含参数序号、类型、实际值。DLCK used time: X(us):数据字典锁耗时,单位微秒,反映元数据访问效率。MORE_RESULT:SQL 执行完成,展示更多结果集。FETCH DATA:客户端从结果集拉取数据,大结果集、分页场景会多次出现。CLOSE STMT:关闭语句句柄,释放内存,SQL 执行收尾。当事务发生封锁冲突并结束等待时,会生成精确版锁日志,可直接看到等待了哪些事务:
trx[480521] LOCK_TID (mode:X, table id:1143) wait for 3 trxs, trx[480511, 480512, 480513] used time:23896(ms)
| 字段 | 说明 |
|---|---|
| trx[480521] | 当前等待的事务 ID |
| LOCK_TID | 事务锁;对象锁显示为 LOCK_OBJ |
| mode:X | 排他锁;还可能是 S 共享锁、IS 意向共享、IX 意向排他 |
| wait for 3 trxs | 等待 3 个事务释放锁 |
| trx[480511, ...] | 具体被等待的事务 ID 列表 |
| used time:23896(ms) | 本次锁等待总耗时 |
在 DSC 集群等场景下,本地节点可能无法获取完整的冲突事务信息,此时输出粗略版:
trx[480521] LOCK_TID (mode:X, table id:1143, tid[480511]) wait used time:23896(ms)
至少会打印一个等待事务 ID,可据此进一步追溯整条阻塞链路。
事务的增删改操作会产生回滚页,日志产生回滚页,日志中常见以下四种回滚页事件:
trx[32072] alloc pseg page[0, 28557], page_lsn[10612892], n_pages[13843]
trx[32076]: purg2_page free pseg page (0, 14169), page_lsn = 14169
trx[32076]: pseg_reset_last_page free pseg page (0, 14169)
trx[32076]: pseg_rollback free pseg page (0, 14169) page_lsn[12592786]
当发现大量回滚页分配、回滚操作频繁时,通常意味着长事务、大批量更新或异常回滚较多,需要关注事务大小与 UNDO 表空间压力。
SQL 日志是达梦数据库运维排查的"第一现场"。从开启配置、读懂事务与锁日志,完整的 sqllog 分析能力,是掌握sql优化能力中必不可少的一部分。建议在实际应用场景中,按需开启 SQL 日志,合理设置掩码与文件切换策略,既保留排查线索,又避免磁盘与性能开销过高。
文章
阅读量
获赞
