小亦平台会持续给大家科普一些Oracle数据库的应急处理方案,运维朋友们可以在应急处理方案专栏查看更多案例。
问题概述
场景描述:操作系统可以telnet但系统出现内存大量换页时,paging space利用率持续增长,此时可能出现可以登陆数据库和无法登陆数据库两种情况,此时适用该场景。
问题分析
内存泄漏是指应用程序或进程在分配内存后未能正确释放,导致可用内存逐渐减少的现象。在 Oracle 环境中:
-
PGA/SGA 泄漏: Oracle 后台进程或用户会话持续占用内存且不释放,常见于 PGA 内存管理异常(如大量排序操作未释放)、SGA 组件(如 buffer cache、shared pool)异常增长。
-
系统级影响: 当物理内存耗尽时,操作系统开始使用 paging space (交换空间/虚拟内存) 进行换页操作,导致 paging space利用率持续增长。这会引发严重的性能下降,表现为:
- 系统响应迟缓
- 进程调度延迟
- 数据库操作挂起或响应极慢
- 两种状态:
- 可登录数据库: 数据库实例仍在运行但性能极差,部分功能可能受限。
- 无法登录数据库: 数据库实例因内存压力已挂起或无响应。
解决方案
- 信息收集
- 无法登陆数据库时
由于数据库挂起,因此需要分两步走,先按照场景2收集造成挂起的信息,再按照下列步骤收集导致内存泄漏的关键信息。
root用户登陆,从操作系统命令判断出消耗大量内存的进程号
#svmon -Pg -t 20
#svmon -Pt -t 20
#ps aux|head -1;ps aux|grep -v grep|sort -n +4
然后oracle用户登陆使用-prelim参数绕过无法登陆数据库的问题,收集前3个最占用内存的进程
$sqlplus -prelim "/as sysdba"
SQL>oradebug setospid XX ---> XX为操作系统进程号
SQL>oradebug dump heapdump 536870917
SQL>oradebug dump processstate 10
SQL>oradebug tracefile_name
SQL>oradebug short_stack
SQL>oradebug short_stack
说明:上述命令中的536870917和10为固定的关键字,不需要修改
同时收集操作系统信息(可选,时间允许情况下进行)
root用户登陆,从操作系统命令判断出消耗大量内存的进程号
#svmon -Pg -t 20
#svmon -Pt -t 20
#ps aux|head -1;ps aux|grep -v grep|sort -n +4
#truss --p XX ----XX为进程号
- 可以登陆数据库时
oracle用户,登陆数据库收集前3个最占用内存的操作系统进程号
$sqlplus "/as sysdba"
select * from gv$pgastat;
select a.sid,
a.serial#,
a.status,
b.spid,
a.username,
a.sql_id,
a.last_call_et,
round(b.PGA_USED_MEM/1024/1024,0) PGA_USED_MEM_M ,
round(b.PGA_ALLOC_MEM/1024/1024,0) PGA_ALLOC_MEM_M,
round(b.PGA_MAX_MEM/1024/1024,0) PGA_MAX_MEM_M
from v$session a, v$process b
where
a.paddr = b.addr
and PGA_ALLOC_MEM / 1024 / 1024 > 200
order by b.PGA_ALLOC_MEM;
-----------此处显示的结果为进程占用内存从小到大的排序,查看第三列spid即可获得操作系统进程号
-----------下面的SQL语句查询出了这些进程正在执行的SQL语句,即可找到泄漏点
select a.sid,
a.serial#,
a.status,
b.spid,
a.username,
a.last_call_et,
round(b.PGA_USED_MEM/1024/1024,0) PGA_USED_MEM_M ,
round(b.PGA_ALLOC_MEM/1024/1024,0) PGA_ALLOC_MEM_M,
round(b.PGA_MAX_MEM/1024/1024,0) PGA_MAX_MEM_M,
a.program,a.machine,a.username,
c.sql_text
from v$session a, v$process b, v$sqltext c
where a.paddr = b.addr
and a.sql_id = c.sql_id
and b.PGA_ALLOC_MEM / 1024 / 1024 > 200
order by a.sid,a.serial#,c.piece;
SQL>oradebug setospid XX -->
XX为操作系统进程号,依次收集最占用内存的前几个进程
SQL>oradebug dump heapdump 536870917
SQL>oradebug dump processstate 10
SQL>oradebug tracefile_name
SQL>oradebug short_stack
SQL>oradebug short_stack
说明:上述命令中的536870917和10为固定的关键字,不需要修改
同时收集操作系统信息(可选,时间允许情况下进行)
root用户登陆,从操作系统命令判断出消耗大量内存的进程号
#svmon -Pt -t 20
#ps aux|head -1;ps aux|grep -v grep|sort -n +4
#truss --p XX ----XX为进程号,收集10秒即可ctrl+c取消
- 杀掉个别前台进程或者重新启动实例
如果是个别前台进程占用大量内存导致,则杀掉该进程
否则登陆数据库时使用下面方法正常重启实例
$sqlplus "/as sysdba"
SQL>shutdown immediate;
SQL>startup;
- 无法登陆使用上述方法重启时则
ps --ef|grep ora_pmon
kill -9 "pmon进程的操作系统进程"
点击即刻前往小亦知识库查看应急预案完整版:www.ces-xiaoyi.com.cn/#/welcome/k…
运维工作中遇到难题?立即提交工单:www.ces-xiaoyi.com.cn/#/workOrder… 小亦平台工程师火速响应,助您快速修复故障!