正文先获取硬件信息获取达梦基本信息vlicens 优先排查 MAX_CPU_NUM查看达梦内存分配状态dual 方式一v sysstat 方式二:正在执行的SQL统计不同账号连接的数量慢SQL排查查看缓冲池命中率内存分配查看死锁杀死 Session查询历史死锁查看当前活跃的会话消耗的内存统计信息(提升很有效)统计信息概述收集统计信息手动收集自动收集查看统计信息更新统计信息删除统计信息
近期遇到生产数据库机器响应特别慢的场景。特别翻了达梦的文档。官方说的内容太多了,做点小总结,快速定位问题。一些工具可能比较好用可参考(我理解为运维实施的范畴,也不应该由开发人员随便操作生产环境):https://eco.dameng.com/document/dm/zh-cn/ops/tool-monitor.html
安装前对数据库有对应规划:https://eco.dameng.com/document/dm/zh-cn/ops/before-installation.html# 比如磁盘性能:参考:
性能诊断:https://eco.dameng.com/document/dm/zh-cn/ops/performance-diagnosis.html
性能优化:https://eco.dameng.com/document/dm/zh-cn/ops/performance-optimization.html
sql执行计划分析:https://cloud.tencent.com/developer/article/2496574
硬件 | 硬件配置(命令) | 运行情况(命令) |
---|---|---|
CPU | cat /proc/cpuinfo | top\vmstat\sar |
内存 | cat /proc/meminfo | top\vmstat\free |
磁盘 | RAID | iostat |
网络 | ifconfig | ping\route\netstat |
不同Linux操作系统,可能命名不一定都齐全。无所谓,能看多少看多少。
看下磁盘压力 iostat -xmd
参考:参数讲解:http://linux.zanglikun.com/c/iostat.html
[root@VM-4-14-centos ~]# iostat -xmd
Linux 3.10.0-1160.81.1.el7.x86_64 (VM-4-14-centos) 2025年04月07日 _x86_64_ (4 CPU)
Device: rrqm/s wrqm/s r/s w/s rMB/s wMB/s avgrq-sz avgqu-sz await r_await w_await svctm %util
vda 0.03 14.74 2.58 16.61 0.06 0.36 45.39 0.05 2.69 3.94 2.50 0.90 1.74
scd0 0.00 0.00 0.00 0.00 0.00 0.00 7.20 0.00 0.46 0.46 0.00 0.46 0.00
查看达梦版本信息
SELECT * FROM V$VERSION LIMIT 100;
输出
DM Database Server 64 V8
8.1
安全版
DB Version: 0x7000c
0XXXXXXXXX-20240712-234979-20093
Msg Version: 0
Gsu level(3-4) cnt: 3
Gsu level(5) cnt: 0
其他重要的排查信息
会话数: SELECT COUNT(*) FROM V$SESSIONS LIMIT 10;
事务数: SELECT COUNT(*) FROM V$TRX LIMIT 10;
等待事件:SELECT * FROM V$TRXWAIT LIMIT 100;
内存池: SELECT * FROM V$MEM_POOL LIMIT 100;
DATE_GEN:数据库安装时间
EXPIRED_DATE:证书过期时间
MAX_CPU_NUM:可使用最大核心数
-- 关注MAX_CPU_NUM。这个可能会出现“一核有难,7核观战”的情况
SELECT * FROM v$license LIMIT 100;
-- 总内存由 “系统缓冲区大小”与“共享内存池大小”共同组成。两者任意过大,都对整体性能影响很大。建议均衡配置。
-- BUFFER_SIZE:系统缓冲区大小,以 M 为单位。推荐值:系统缓冲区大小为可用物理内存的 60%~80%。有效值范围(8~1048576)。
-- MEM_POOL:共享内存池大小,以 M 为单位。共享内存池是由 DM 管理的内存。有效值范围:32 位平台为(642000),64 位平台为(6467108864)。
-- TOTAL_SIZE:BUFFER_SIZE 和 MEM_POOL 的总和。
SELECT
(SELECT SUM(n_pages) * PAGE()/1024/1024 FROM v$bufferpool)||'MB' AS 系统缓冲区大小,
(SELECT SUM(total_size)/1024/1024 FROM v$mem_pool)||'MB' AS 共享内存池大小,
(SELECT SUM(n_pages) * PAGE()/1024/1024 FROM v$bufferpool)+(SELECT SUM(total_size)/1024/1024 FROM v$mem_pool)||'MB' AS 总内存大小TOTAL_SIZE
FROM DUAL LIMIT 10;
SELECT name, stat_val/1024.0/1024.0 FROM v$sysstat where CLASSID=11 LIMIT 10;
查询结果中,字段含义如下:
查看正在执行的SQL
-- 查询当前连接的信息。
SELECT
SYSDATE AS "当前时间,非字段",
USER_NAME AS "连接的账号",
STATE AS "状态",
SF_GET_SESSION_SQL(SESS_ID) AS "完整SQL",
SESS_ID AS "会话 ID,会话唯一标识",
SESS_SEQ ,
--SQL_TEXT ,
SEQ_NO ,
TRX_ID AS "事务号",
CREATE_TIME ,
CLNT_IP AS "客户端IP"
-- CLNT_HOST AS "客户端主机名",
-- APPNAME AS "客户端名称",
-- OSNAME AS "客户端操作系统"
FROM
v$sessions
WHERE
STATE IN ('ACTIVE', 'WAIT') LIMIT 100;
-- STATE有:ACTIVE=活跃的、WAIT=等待的、IDLE=闲置的。因为各种应用都会配备数据库连接池,就会有很多IDLE的连接。所以排查问题就不查询IDLE的状态了。
-- 统计不同账号连接的数量
SELECT
STATE AS "状态",
USER_NAME AS "连接的账号",
COUNT(1) AS "数量"
FROM
v$sessions
GROUP BY
STATE,USER_NAME
LIMIT 100
;
-- 慢日志记录信息
SELECT
SESS_ID AS "会话 ID,会话唯一标识",
-- SQL_ID AS "语句 ID,语句唯一标识",
SQL_TEXT AS SQL文本,
EXEC_TIME AS "执行时间(毫秒)",
FINISH_TIME AS "执行结束时间",
N_RUNS AS "执行次数",
SEQNO AS "编号",
TRX_ID AS "事务号"
FROM
V$LONG_EXEC_SQLS
LIMIT 100;
SELECT
NAME AS "缓冲池名称",
SUM(PAGE_SIZE) * SF_GET_PAGE_SIZE / 1024 / 1024 AS "缓冲池大小_MB",
SUM(RAT_HIT) / COUNT(*) AS "命中率"
FROM
v$bufferpool
GROUP BY NAME LIMIT 100;
注意一个事项:缓冲池不是真实物理内存占用。
输出:
KEEP 1024 1
RECYCLE 3072 0.9513388117336025
FAST 1024 0.9999996457697699
NORMAL 9216 0.9777671570939879
ROLL 1024 1
SELECT
DS.SESS_ID "被阻塞的会话ID",
DS.SQL_TEXT "被阻塞的SQL",
DS.TRX_ID "被阻塞的事务ID",
(CASE L.LTYPE WHEN 'OBJECT' THEN '对象锁' WHEN 'TID' THEN '事务锁' END CASE ) "被阻塞的锁类型",
DS.CREATE_TIME "开始阻塞时间",
SS.SESS_ID "占用锁的会话ID",
SS.SQL_TEXT "占用锁的SQL",
SS.CLNT_IP "占用锁的IP",
L.TID "占用锁的事务ID"
FROM
V$LOCK L
LEFT JOIN V$SESSIONS DS
ON
DS.TRX_ID = L.TRX_ID
LEFT JOIN V$SESSIONS SS
ON
SS.TRX_ID = L.TID
WHERE
L.BLOCKED = 1
LIMIT 100;
SP_CLOSE_SESSION ( 占用锁的会话 ID );
SELECT
DH.TRX_ID AS "事务ID",
SH.SESS_ID AS "SESSION_ID",
WM_CONCAT(TOP_SQL_TEXT) AS "SQL"
FROM
V$DEADLOCK_HISTORY DH,
V$SQL_HISTORY SH
WHERE
DH.TRX_ID =SH.TRX_ID
AND DH.SESS_ID=SH.SESS_ID
GROUP BY
DH.TRX_ID, SH.SESS_ID
LIMIT 100;
-- 查看当前活跃的会话消耗的内存
SELECT
B.CURR_SCH AS "当前模式",
B.USER_NAME AS "操作账号",
B.SESS_ID AS "SESSION_ID",
A.CREATOR ,
B.SQL_TEXT ,
SUM(A.TOTAL_SIZE)/1024.0/1024.0 TOTAL_M, --当前总量(包括扩展)
SUM(A.DATA_SIZE) /1024.0/1024.0 DATA_SIZE_M --实际使用量
FROM
V$MEM_POOL A,
V$SESSIONS B
WHERE
A.CREATOR = B.THRD_ID
AND B.STATE = 'ACTIVE'
GROUP BY
A.CREATOR,
B.SQL_TEXT
ORDER BY
TOTAL_M DESC
LIMIT 1000;
统计信息主要是描述数据库中表和索引的大小数以及数据分布状况等的一类信息。比如:表的行数、块数、平均每行的大小、索引的高度、叶子节点数以及索引字段的行数等。
统计信息对于 CBO(基于代价的优化器)生成执行计划具有直接影响。例如在嵌套循环连接(链接)中需要选择小表作为驱动表,两个关联表哪个是小表完全取决于统计信息中记录的数据量信息。此外,访问一个表是否要走索引,关联查询能否采用其它关联方式等都是 CBO 基于统计信息确定的。因此,统计信息的准确是生成最优执行计划的必要前提。
DM 收集统计信息的方法分为手动收集和自动收集。
--收集指定用户下所有表所有列的统计信息:
DBMS_STATS.GATHER_SCHEMA_STATS('username',100,TRUE,'FOR ALL COLUMNS SIZE AUTO');
--收集指定用户下所有索引的统计信息:
DBMS_STATS.GATHER_SCHEMA_STATS('usename',1.0,TRUE,'FOR ALL INDEXED SIZE AUTO');
--或 收集单个索引统计信息:
DBMS_STATS.GATHER_INDEX_STATS('username','IDX_T2_X');
--收集指定用户下某表统计信息:
DBMS_STATS.GATHER_TABLE_STATS('username','table_name',null,100,TRUE,'FOR ALL COLUMNS SIZE AUTO');
--收集某表某列的统计信息:
STAT 100 ON table_name(column_name);
注意 统计信息收集过程中将对数据库性能造成一定影响,避免在业务高峰期收集统计信息。 自动收集
DM 数据库支持统计信息的自动收集,当全表数据量变化超过设定阈值后可自动更新统计信息。
--打开表数据量监控开关,参数值为 1 时监控所有表,2 时仅监控配置表
SP_SET_PARA_VALUE(1,'AUTO_STAT_OBJ',2);
--设置 SYSDBA.T 表数据变化率超过 15% 时触发自动更新统计信息
DBMS_STATS.SET_TABLE_PREFS('SYSDBA','T','STALE_PERCENT',15);
--配置自动收集统计信息触发时机
SP_CREATE_AUTO_STAT_TRIGGER(1, 1, 1, 1,'14:36', '2020/3/31',60,1);
/*
函数各参数介绍
SP_CREATE_AUTO_STAT_TRIGGER(
TYPE INT, --间隔类型,默认为天
FREQ_INTERVAL INT, --间隔频率,默认 1
FREQ_SUB_INTERVAL INT, --间隔频率,与 FREQ_INTERVAL 配合使用
FREQ_MINUTE_INTERVAL INT, --间隔分钟,默认为 1440
STARTTIME VARCHAR(128), --开始时间,默认为 22:00
DURING_START_DATE VARCHAR(128), --重复执行的起始时间,默认 1900/1/1
MAX_RUN_DURATION INT, --允许的最长执行时间(秒),默认不限制
ENABLE INT --0 关闭,1 启用 --默认为 1
);
*/
--用于经过 GATHER_TABLE_STATS、GATHER_INDEX_STATS 或 GATHER_SCHEMA_STATS 收集之后展示。
dbms_stats.table_stats_show('模式名','表名');
--用于经过 GATHER_TABLE_STATS、GATHER_INDEX_STATS 或 GATHER_SCHEMA_STATS 收集之后展示。 返回两个结果集:一个是索引的统计信息;另一个是直方图的统计信息。
dbms_stats.index_stats_show('模式名','索引名');
--用于经过 GATHER_TABLE_STATS、GATHER_INDEX_STATS 或 GATHER_SCHEMA_STATS 收集之后展示。
dbms_stats.COLUMN_STATS_SHOW('模式名','表名','列名');
--更新已有统计信息
DBMS_STATS.UPDATE_ALL_STATS();
--表DBMS_STATS.DELETE_TABLE_STATS('模式名','表名','分区名',...);
--模式
DBMS_STATS.DELETE_SCHMA_STATS('模式名','','',...);
--索引
DBMS_STATS.DELETE_INDEX_STATS('模式名','索引名','分区表名',...);
--字段
DBMS_STATS.DELETE_COLUMN_STATS('模式名','表名','列名','分区表名',...);
特殊说明:
上述文章均是作者实际操作后产出。烦请各位,请勿直接盗用!转载记得标注原文链接:[www.zanglikun.com](https://www.zanglikun.com/)
第三方平台不会及时更新本文最新内容。