一、会话监控:
1.1.SQL 方法查询会话数
--查询当前所有会话数
select count(*) from v$sessions;
--查看当前数据库中活动会话
select count(*) from v$sessions where state='ACTIVE';
--查看当前非活动会话
select count(*) from v$sessions where state='IDLE';
--结束会话
sp_close_session(sess_id);
1.2.操作系统命令查询会话数
--基于端口为 5236 的会话数查询
lsof -i:5236|grep dmserver|wc -l
netstat -nat|awk '{print $4}'|grep 5236|wc -l
查看当前活动会话时,若当前活动会话连接数量太大,则说明数据库当前可能存在以下异常情况:
1).当前业务繁忙,业务量太大;
2).当前系统中存在慢 SQL;
3).应用的重连机制存在缺陷。
查看当前非活动会话时,若当前非活动会话连接数量太大,说明数据库可能存在以下情况:
1).系统当前处于会话空闲期;
2).连接池会话上线设置过高;
3).应用释放连接机制存在异常。
二、线程监控:
线程监控主要监控数据库中活动线程信息和等待线程信息。
2.1.监控当前系统中活动线程的信息。
SELECT * FROM V$THREADS;
2.2.监控当前正在等待的线程信息。
SELECT * FROM V$LATCHES;
三、SQL 监控
SQL 监控主要包括慢 SQL 及阻塞、死锁、有事务未提交的表等。
3.1.慢 SQL 及阻塞监控
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
3.2.查询死锁历史事务信息
select
dh.trx_id ,
sh.sess_id,
wm_concat(top_sql_text)
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;
3.3.有事务未提交的表查询
SELECT b.object_name, c.sess_id, a.*
FROM v$lock a, dba_objects b, v$sessions c
WHERE a.table_id = b.object_id AND ltype = 'OBJECT' AND a.trx_id = c.trx_id;
四、内存监控
select
(select sum(n_pages * page_size)/1024/1024 from v$bufferpool)||'MB' as BUFFER_SIZE,
(select sum(total_size)/1024/1024 from v$mem_pool)||'MB' as mem_pool,
(select sum(n_pages * page_size)/1024/1024 from v$bufferpool)+(select sum(total_size)/1024/1024 from v$mem_pool)||'MB' as TOTAL_SIZE
from dual;
以上查询结果中,字段含义如下:
- BUFFER_SIZE:系统缓冲区大小,以 M 为单位。推荐值:系统缓冲区大小为可用物理内存的 60%~80%。有效值范围(8~1048576)
- MEM_POOL:共享内存池大小,以 M 为单位。共享内存池是由 DM 管理的内存。有效值范围:32 位平台为(642000),64 位平台为(6467108864)
- TOTAL_SIZE:BUFFER_SIZE 和 MEM_POOL 的总和。
内存不足常见原因有如下两种情况:
- memory_target 设置为 0,导致会话使用的内存未释放,可以考虑修改 memory_target 参数。
- 会话执行的 sql 消耗大量的内存,可以根据以下 sql 找到最占用内存的 sql,再进行 sql 优化。
SELECT "SESSID", MAX_MEM_USED||'KB',SQL_TXT FROM V$SQL_STAT
order by MAX_MEM_USED DESC;
4.1.查看所有内存池的使用信息
方法一:查询内存池使用信息的 sql 语句如下所示,单位是 M
select
name, --内存池名称
is_shared, --是否是共享的
is_overflow, --是否用到了备份池
org_size/1024.0/1024.0, --内存池初始大小
TOTAL_size/1024.0/1024.0, --内存池总大小(包括扩展的)
RESERVED_SIZE/1024.0/1024.0, --当前已分配大小(包括扩展的)
DATA_SIZE/1024.0/1024.0, --实际有效字节
EXTEND_SIZE, --每次扩展多少
TARGET_SIZE, --目标大小
N_EXTEND_NORMAL , --TARGET范围内累计扩展次数
N_EXTEND_EXCLUSIVE --超过TARGET累计扩展次数
from v$mem_pool
order by TOTAL_size desc;
查询结果可以参考如下:
(1)N_EXTEND_EXCLUSIVE 如果长期大于 0,说明长期从池外扩展,可能存在内存泄露,需要重点关注。
(2)若使用到备份池,则需要保持高度关注。
(3)内存池创建的线程号 creator 可以与 session 的 thrd_id 关联,查看对应的某个会话的内存使用情况。
(4)若 RESERVED_SIZE 比 org_size 小,说明内存池非常空闲,可以减小对应的初始内存,避免浪费。
(5)若 TOTAL_size 比 TARGET_SIZE 大,说明内存池不够,经常向池外申请,需要把对应参数调大。
方法二:可以通过 v$sysstat 视图监控内存的使用情况。
select name ,stat_val/1024.0/1024.0 from v$sysstat where CLASSID=11 ;
4.2.单个会话内存使用情况
SELECT
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
GROUP BY
A.CREATOR,
B.SQL_TEXT
ORDER BY
TOTAL_M DESC;
4.3内存增长过快分析
(1)通过查询内存的使用,确定增长范围。
select
(select sum(n_pages * page_size)/1024/1024 from v$bufferpool)||'MB' as BUFFER_SIZE,
(select sum(total_size)/1024/1024 from v$mem_pool)||'MB' as mem_pool,
(select sum(n_pages * page_size)/1024/1024 from v$bufferpool)+(select sum(total_size)/1024/1024 from v$mem_pool)||'MB' as TOTAL_SIZE
from dual;
在启动前查询上述语句,记录初始值。然后在内存增长的时候,再查询上述语句。
(2)打开 MEMORY_LEAK_CHECK
alter system set 'MEMORY_LEAK_CHECK'=1 ;
(3)查询 V$MEM_REGINFO 视图,关注 REFNUM 字段,若该字段值很大,则说明存在内存堆积的情况。
select * from V$MEM_REGINFO ORDER BY REFNUM DESC;
4.4.查询缓冲区命中率
数据缓冲区是 DMSERVER 在将数据页写入磁盘之前以及从磁盘上读取数据页之后,数据页所存储的地方。
数据缓冲区设定得太小,会导致缓冲页命中率低,磁盘 IO 频繁;将其设定得太大,又会导致操作系统内存本身不够用。
select
name 缓冲池名称,
sum(page_size)*sf_get_page_size 缓冲池大小_G,
sum(rat_hit) /count(*) 命中率
from
v$bufferpool
group by name;
五、表空间监控
表空间监控主要监控数据库表空间使用率。需要注意以下内容:
- 表空间监控主要关注业务表空间、ROLL 表空间和 TEMP 表空间;
- 不同业务数据使用独立表空间,建议不要使用 MAIN 表空间;
- 可以根据实际业务需求对表空间设置阈值上限。
5.1.查看表空间的使用情况
SELECT Upper(F.TABLESPACE_NAME) "表空间名",
D.TOT_GROOTTE_MB "表空间大小(M)",
D.TOT_GROOTTE_MB - F.TOTAL_BYTES "已使用空间(M)",
To_char(Round(( D.TOT_GROOTTE_MB - F.TOTAL_BYTES ) / D.TOT_GROOTTE_MB * 100, 2), '990.99')
|| '%' "使用比",
F.TOTAL_BYTES "空闲空间(M)",
F.MAX_BYTES "最大块(M)"
FROM (SELECT TABLESPACE_NAME,
Round(Sum(BYTES) / ( 1024 * 1024 ), 2) TOTAL_BYTES,
Round(Max(BYTES) / ( 1024 * 1024 ), 2) MAX_BYTES
FROM SYS.DBA_FREE_SPACE
GROUP BY TABLESPACE_NAME) F,
(SELECT DD.TABLESPACE_NAME,
Round(Sum(DD.BYTES) / ( 1024 * 1024 ), 2) TOT_GROOTTE_MB
FROM SYS.DBA_DATA_FILES DD
GROUP BY DD.TABLESPACE_NAME) D
WHERE D.TABLESPACE_NAME = F.TABLESPACE_NAME
ORDER BY 2 desc;
临时表空间经常过大,说明内存设置过小或存在大量中间结果集存放,需要视情况进行优化。
为了不影响磁盘空间的使用,可以通过 ini 参数 TEMP_SIZE 配置大小、TEMP_SPACE_LIMIT 设置上限、存储过程 SP_TRUNC_TS_FILE 来收缩 TEMP 表空间文件(生产环境请谨慎使用)。
5.2.查看表空间与数据文件对应关系
SELECT TS.NAME, DF.PATH FROM V$TABLESPACE AS TS, V$DATAFILE AS DF WHERE TS.ID = DF.GROUP_ID;