当数据库突然变慢,最直观的反应就是查看当前正在执行的SQL。达梦提供了动态视图 V$SESSIONS 和 V$SQL_STAT,我们可以关联查询,获取会话状态、执行时间、客户端IP以及完整的SQL文本。
下面是一条实用的监控SQL,它会列出所有处于 ACTIVE 或 WAIT 状态的会话,并计算SQL已执行的时间(秒),同时提供关闭会话的快捷语句(以防紧急kill):
SELECT * FROM (
SELECT 'SP_CLOSE_SESSION('||SESS_ID||');' AS CLOSE_SESSION,
DATEDIFF(SS,LAST_SEND_TIME,SYSDATE) sql_exectime,
TRX_ID,
CLNT_IP,
B.IO_WAIT_TIME AS IO_WAIT_TIME,
SF_GET_SESSION_SQL(SESS_ID) FULLSQL,
A.SQL_TEXT
FROM V$SESSIONS a,V$SQL_STAT B WHERE STATE IN ('ACTIVE','WAIT')
AND A.SESS_ID = B.SESSID
)
SQL_TEXT列记录的是部分SQL语句,FULLSQL列存储了完整的执行SQL语句,需要记录保存下来,针对这些SQL语句进行优化。
模拟慢sql:为了演示,创建两张表 DM(5万行)和 EM(500万行),并在关联字段上建立索引,然后执行一个带有 UPPER 函数和 OR 条件的查询,该查询会导致索引失效,从而产生全表扫描,执行时间显著变长。
-- 1. 创建小表 dm,用于关联查询
DROP TABLE IF EXISTS DM;
CREATE TABLE DM (
DID INT PRIMARY KEY IDENTITY(2,3),
ENAME VARCHAR(200),
DEPTNO INT
);
-- 插入5万条数据
DECLARE I INT;
BEGIN
FOR I IN 1..50000 LOOP
INSERT INTO DM (ENAME, DEPTNO)
SELECT
DBMS_RANDOM.STRING('2', TRUNC(DBMS_RANDOM.VALUE(2,4))),
TRUNC(DBMS_RANDOM.VALUE(1,6))
FROM DUAL;
END LOOP;
END;
/
-- 2. 创建大表 em,模拟主要数据表
DROP TABLE IF EXISTS EM;
CREATE TABLE EM (
EID INT PRIMARY KEY IDENTITY(1,1),
ENAME VARCHAR(200),
AGE INT,
HIREDATE DATE,
DEPTNO INT
);
-- 插入500万条数据
DECLARE I INT;
BEGIN
FOR I IN 1..5000000 LOOP
INSERT INTO EM (ENAME, AGE, HIREDATE, DEPTNO)
SELECT
DBMS_RANDOM.STRING('2', TRUNC(DBMS_RANDOM.VALUE(2,4))),
TRUNC(DBMS_RANDOM.VALUE(1,100)),
ADD_DAYS(SYSDATE(), DBMS_RANDOM.VALUE(-10000,-10)),
TRUNC(DBMS_RANDOM.VALUE(1,6))
FROM DUAL;
END LOOP;
END;
/
-- 3. 为关联字段创建索引
CREATE INDEX IDX_EM_ENAME ON EM(ENAME);
CREATE INDEX IDX_DM_ENAME ON DM(ENAME);
-- 4. 收集统计信息,帮助优化器生成执行计划
DBMS_STATS.GATHER_TABLE_STATS('SYSDBA','DM',NULL,100,TRUE,'FOR ALL COLUMNS SIZE AUTO');
DBMS_STATS.GATHER_TABLE_STATS('SYSDBA','EM',NULL,100,TRUE,'FOR ALL COLUMNS SIZE AUTO');
执行一个可能导致全表扫描或复杂关联的查询。下面的SQL可能会因为函数,导致优化器放弃使用索引而选择全表扫描。
-- 执行一个可能很慢的查询
SELECT EM.*
FROM EM
JOIN DM ON UPPER(EM.ENAME) = UPPER(DM.ENAME) -- 使用函数,索引失效
WHERE (EM.EID = 3 AND EM.AGE = 67)
OR (EM.EID = 5 AND EM.AGE = 20);
第一个是监控的sql,第二个能看到正在执行的慢sql,他的语句信息、执行信息、事务id
通过分析dmsql_log日志来获取哪些SQL语句慢,需要掌握Dmlog分析工具的使用方法以及需要安装jdk环境。
为避免记录SQL log对服务器产生较大的影响,还需要配置异步日志刷新ASYNC_FLUSH = 1。
开启sqllog
SP_SET_PARA_VALUE(1, 'SVR_LOG', 1);
只执行了一条查询语句的log也是非常多的,所以我们可以通过grep去过滤对我们有用的信息,比如执行时间:
[root@localhost log]# cat dmsql_PROD_20260727_171401.log | grep EXECTIME
OR (EM.EID = 5 AND EM.AGE = 20); EXECTIME: 13562(ms) ROWCOUNT: 0(rows) EXEC_ID: 834.
and SF_COL_IS_IDX_KEY(INDS.KEYNUM, INDS.KEYINFO, COLS.COLID) = 1; EXECTIME: 64(ms) ROWCOUNT: 1(rows) EXEC_ID: 835.
2026-07-27 17:14:20.275 (EP[0] sess:0x7f7f9c020328 thrd:3434 user:SYSDBA trxid:0 stmt:0x7f7f9c040a00 appname:manager ip:::ffff:127.0.0.1) [SEL] /***Manager***/ SELECT count(*),max(trxid) from SYS.SYSOBJECTS; EXECTIME: 42(ms) ROWCOUNT: 1(rows) EXEC_ID: 1426.
2026-07-27 17:16:00.565 (EP[0] sess:0x7f7f9c020328 thrd:3434 user:SYSDBA trxid:0 stmt:0x7f7f9c040a00 appname:manager ip:::ffff:127.0.0.1) [SEL] /***Manager***/ SELECT count(*),max(trxid) from SYS.SYSOBJECTS; EXECTIME: 58(ms) ROWCOUNT: 1(rows) EXEC_ID: 1427.
2026-07-27 17:17:40.794 (EP[0] sess:0x7f7f9c020328 thrd:3434 user:SYSDBA trxid:0 stmt:0x7f7f9c040a00 appname:manager ip:::ffff:127.0.0.1) [SEL] /***Manager***/ SELECT count(*),max(trxid) from SYS.SYSOBJECTS; EXECTIME: 16(ms) ROWCOUNT: 1(rows) EXEC_ID: 1428.
性能监控相关参数(ET)
| 参数名称 | 作用与含义 | 开启后可以做什么? | 重要提醒 |
|---|---|---|---|
ENABLE_MONITOR |
监控的总开关。 | 开启后,数据库才会开始收集SQL执行、性能等关键数据,是使用其他监控功能的前提。 | 系统级动态参数。开启会带来一定的性能损耗,建议按需开启,用完即关。 |
MONITOR_SQL_EXEC |
SQL执行细节监控。 | 精确记录SQL语句执行过程中每个操作符的耗时,是使用 ET 和 DBMS_SQLTUNE 等高级分析工具的核心参数。 | 会话级动态参数。强烈建议只在需要分析的会话中开启,避免全局开启影响性能。 |
ENABLE_MONITOR_DMSQL |
DMSQL程序监控。 | 开启对DMSQL程序(如存储过程、函数、触发器)的监控。 | 如果你需要分析存储过程的性能问题,这个参数必须开启。 |
打开监控
SP_SET_PARA_VALUE(1,'ENABLE_MONITOR',1);
SP_SET_PARA_VALUE(1,'MONITOR_SQL_EXEC',1);
通过ET 函数能展示SQL执行计划中每个操作符的具体耗时
CALL ET(执行号)
还可以通过V$LONG_EXEC_SQLS来查看慢sql
配置操作系统保存core文件
[dmdba@localhost bin]$ ulimit -c unlimited
修改core文件路径
[root@localhost ~]# echo "/corefile/core-%e-%p-%t" > /proc/sys/kernel/core_pattern
手动生成core文件
[dmdba@localhost bin]$ ps -ef|grep dmserver
dmdba 3134 1 0 05:35 pts/0 00:00:00 /opt/dmdbms/bin/dmserver /opt/dmdbms/bin/dm.ini -noconsole
dmdba 3210 2778 0 05:37 pts/0 00:00:00 grep dmserver
[dmdba@localhost bin]$ kill -11 3134
当操作系统是麒麟v10时,需要变为以下设置:
[dmdba@localhost bin]$ echo -e “\nkernel.core_pattern=/corefile/core-%e-%s-%p-%t” >>/etc/sysctl.conf
[dmdba@localhost bin]$ echo -e “1” >>/proc/sys/kernel/core_uses_pid
[dmdba@localhost bin]$ sysctl -p /etc/sysctl.conf
利用gdb分析打印堆栈:
dmdba@localhost bin]$ gdb dmserver(可执行文件) core.3134 (core文件)
(gdb) set logging file dmstack.log
(gdb) set logging on
Copying output to dmstack.log.
(gdb) thread apply all bt
… #一直enter直到所有线程打印退出
(gdb) set logging off
Done logging to dmstack.log.
无core文件时
[dmdba@localhost bin]$ ps -ef|grep dmserver
dmdba 3287 1 2 05:51 pts/0 00:00:00 /opt/dmdbms/bin/dmserver /opt/dmdbms/bin/dm.ini -noconsole
dmdba 3398 2778 0 05:51 pts/0 00:00:00 grep dmserver
[dmdba@localhost bin]$ gdb
GNU gdb (GDB) Red Hat Enterprise Linux (7.2-60.el6_4.1)
Copyright (C) 2010 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law. Type "show copying"
and "show warranty" for details.
This GDB was configured as "x86_64-redhat-linux-gnu".
For bug reporting instructions, please see:
<http://www.gnu.org/software/gdb/bugs/>.
(gdb) attach 3287
Attaching to process 3287
Reading symbols from /opt/dmdbms/bin/dmserver...(no debugging symbols found)...done.
Reading symbols from /lib64/librt.so.1...(no debugging symbols found)...done.
Loaded symbols for /lib64/librt.so.1
Reading symbols from /lib64/libpthread.so.0...(no debugging symbols found)...done.
[New LWP 3389]
[New LWP 3388]
…
(gdb) set logging file dmstack.log
(gdb) set logging on
Copying output to dmstack.log.
(gdb) thread apply all bt
…
(gdb) set logging off
(gdb) detach
(gdb) quit
进程不在,一启动就挂,无法attach又core不出来,怎么办?
[dmdba@localhost bin]$ gdb dmserver
GNU gdb (GDB) Red Hat Enterprise Linux (7.2-60.el6_4.1)
Copyright (C) 2010 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law. Type "show copying"
and "show warranty" for details.
This GDB was configured as "x86_64-redhat-linux-gnu".
For bug reporting instructions, please see:
<http://www.gnu.org/software/gdb/bugs/>...
Reading symbols from /opt/dmdbms/bin/dmserver...(no debugging symbols found)...done.
(gdb) r /opt/dmdbms/bin/dm.ini
Starting program: /opt/dmdbms/bin/dmserver /opt/dmdbms/bin/dm.ini
[Thread debugging using libthread_db enabled]
file dm.key not found, use default license!
Read ini warning, default backup path [/dbdata/dmbak] does not exist.
Detaching after fork from child process 3476.
version info: develop
Detaching after fork from child process 3477.
Use normal os_malloc instead of HugeTLB
Use normal os_malloc instead of HugeTLB
DM Database Server x64 V7.6.1.60-Build(2020.06.02-122414)ENT startup...
[New Thread 0x7ffe8f07d700 (LWP 3478)]
[New Thread 0x7ffe8ef7c700 (LWP 3479)]
[New Thread 0x7ffe4d796700 (LWP 3480)]
[New Thread 0x7ffe4d695700 (LWP 3481)]
[New Thread 0x7ffe4d594700 (LWP 3482)]
[New Thread 0x7ffe4d493700 (LWP 3483)]
License will expire on 2021-06-02
[New Thread 0x7ffe4cf49700 (LWP 3484)]
[New Thread 0x7ffe4ce48700 (LWP 3485)]
…
这样在gdb中启动的进程就算由于某些问题core掉,这部分内存数据还是可以在gdb中分析的,可以按照上面gdb分析堆栈的流程进行处理。
文章
阅读量
获赞
