某测试库忽然非常慢,登上去都费劲,先看top,最近1 5 15分钟内负载都达到20多,比较忙。
再看主要忙的进程,是系统的,如system,怎么会这样?
呜呼,swap用完
看看谁占的多(swap是os自己管理,通常是进程占用多导致)
ps aux|sort -rnk4|head
user pid %cpu %mem vsz rss tty stat start time command
oracle 6229 4.1 3.8 8917328 626520 ? rs 06:40 4:29 ora_m005_orcl
oracle 7915 1.9 3.4 8917912 559124 ? ss 07:23 1:16 ora_m001_orcl
oracle 4834 1.6 3.3 8890700 546800 ? ds 06:06 2:22 ora_m003_orcl
oracle 10267 1.6 3.1 8885984 516100 ? ss 08:14 0:13 ora_m000_orcl
oracle 3878 4.0 0.8 8917856 141156 ? ss 05:36 6:58 ora_dia0_orcl
oracle 17733 3.1 0.7 9009416 116000 ? ssl jun30 30:59 ora_gen1_orcl
oracle 3880 6.6 0.7 8903524 123352 ? ss 05:36 11:22 ora_mmon_orcl
oracle 17945 3.6 0.5 8932264 84212 ? rs jun30 36:26 ora_cjq0_orcl
oracle 17755 1.7 0.4 8886892 70748 ? ss jun30 17:09 ora_ckpt_orcl
oracle 17751 0.6 0.4 8895912 77976 ? ss jun30 6:24 ora_dbw0_orcl
物理内存15g,分配sga8g,pga2g,按说不应该超分,是谁占用的?
关于进程占用多少内存,这个问题需要一个方法来确认。
还是上mos,搜索process memory(关键字显示水平)
找到一些,摘取(全抄)如下:
背景
当一个进程启动时,并不是所有的内存都分配在物理内存中。只有一部分(称为常驻集或工作集)保存在物理内存中。其余部分驻留在交换空间中。进程的总内存消耗称为虚拟内存。交换的使用允许所有进程的总虚拟内存组合超过物理内存大小。
在物理内存中,内存块被分配在称为页面的统一块中。一个页面的大小通常为 4kb,但这可能因环境而异。
对于分配的每一页物理内存,操作系统将保留相等的交换空间页。这不是交换。该空间是保留的,以便在必须换出页面时预先分配交换空间。
如何确认正在发生高内存使用率?
发生交换时,物理内存已满。要继续处理,必须换出一些进程页以为新进程腾出空间。这至少需要一个 i/o 操作,通常需要两次,因为已换出的页面最终必须换回。在进程执行中引入 i/o 操作是交换期间性能下降的一个原因。因此,高内存使用率意味着服务器上正在发生交换。
您可以使用 vmstat 测量交换程度:
列 si = 交换入
列 so = 交换出
当列 si 等大于零时,系统正在交换。si 中的值越大,交换的程度就越大。
如何识别导致高内存使用率的进程?
服务器上使用的内存是:
-
非 oracle 内存(必须由系统管理员解决)
-
oracle 内存
oracle 的总内存占用分为两部分,共享内存和私有内存:
共享内存 - sga
sga 大小通常是固定数量,在实例启动时分配。
在手动内存管理中,sga 大小是以下两者中的较大者:
-
sga_max_size
-
sga组件的总和:共享池、java_pool、大池、流池、日志缓冲区、缓冲区缓存。
在自动共享内存管理 (asmm) 中,sga 大小是以下两者中的较大者:
在自动内存管理 (amm) 中 - 在 11g 中引入 - sga 和 pga 内存都包含在 memory_target 中,因此总内存占用将是较大的:
-
memory_target
-
memory_max_target
私有内存 - pga
pga 大小可以在 v$pgastat 中找到,详细信息可以在 v$process 中找到
-
sga 和分配的 pga 之和就是 oracle 内存使用量。
-
在 11g amm 中, memory_max_target 定义了 sga 和 pga,oracle 内存使用也是如此
所有 oracle 进程都会有一部分 pga 内存可以测量,而共享内存则无法测量,因为它被所有进程共享。
查找谁在使用内存的方法如下:
-
从 o/s 的角度来看,什么在使用内存?
-
从数据库的角度来看,什么在使用内存?
-
调和两种观点。
从 o/s 的角度来看,如何查看哪些进程正在使用内存?
使用 unix ps实用程序查看进程实际消耗了多少内存。例如,要获取按内存大小排序的前 50 个进程:
-
solaris: ps -eo user,pid,ppid,vsz,rss,time,comm | sort 4 -5 -n -r | head -50
-
linux: ps aux | sort 5 -6 -n -r | head -50
-
aix: ps aux | sort 5 -6 -n -r | head -50
-
hp-ux: ps -elf | sort 9 -10 -n -r | head -50
内存大小不是绝对的,我们只使用这个输出来获得一个相对大小进行比较。
oracle 进程是最大的内存消耗者。
从 oracle 的角度来看,如何查看哪些进程正在使用内存?
为此,您可以查询 v$process:
-
set linesize 120
-
set pagesize 120
-
column spid heading 'ospid' format a8
-
column pid heading 'orapid' format 999999
-
column sid heading 'sess id' format 99999
-
column serial# heading 'serial#' format 999999
-
column status heading 'status' format a8
-
column pga_alloc_mem heading 'pga alloc' format 99,999,999,999
-
column pga_used_mem heading 'pga used' format 99,999,999,999
-
column username heading 'oracle user' format a12
-
column osuser heading 'os user' format a12
-
column program heading 'program' format a26
-
-
-
select * from (
-
select p.spid,
-
p.pid,
-
s.sid,
-
s.serial#,
-
s.status,
-
round(p.pga_alloc_mem/1024/1024) alloc_m,
-
round(p.pga_used_mem/1024/1024) used_m,
-
s.username,
-
s.osuser,
-
s.program
-
from v$process p, v$session s
-
where s.paddr( ) = p.addr
-
order by p.pga_alloc_mem desc) where rownum<21;
前20个占用较多的会话。
pga 的总使用量:
-
select round(sum(pga_alloc_mem)/1024/1024,1) as "allocated mbytes", round(sum(pga_used_mem)/1024/1024,1) as "used mbytes" from v$process;
如何协调 o/s 内存用户与 oracle 内存用户?
可以检查以下区域以查看 oracle 内存消耗是否过多和/或使用效率低下。
-
最高的 o/s 内存消耗者也是最高的 pga 消耗者吗? 不是默认的。这必须在 oracle 外部以及在 v$pgastat 或 v$process 中进行调查。pga 只是 oracle 内存消耗总量的一部分。大量的 oracle 内存消耗并不自动意味着大量的 pga 消耗(还要考虑 sga 大小)。
-
是否是单个 oracle 进程导致大部分内存分配? 如果单个进程消耗过多内存,可以使用堆转储等分析机制来查看是否遇到错误情况。
要获取堆转储,请使用上述查询获取违规进程的 ospid,然后发出:
-
sqlplus /nolog
-
connect / as sysdba
-
alter system set max_dump_file_size=unlimited;
-
alter system set events '10235 trace name context forever, level 65536';
-
connect / as sysdba
-
oradebug setospid
-
oradebug unlimit
-
oradebug dump errorstack 10
-
oradebug dump heapdump 536870917
-
oradebug tracefile_name -- this shows the location of the trace file generated
-
oradebug close_trace -- this closes the trace file
-
alter system set events '10235 trace name context off';
-
exit
-
是否有多个 oracle 进程占用了所有内存? 如果多个 oracle 进程消耗了所有可用内存,则可能是我们的占用内存过多。检查是否需要所有当前正在运行的进程(例如检查 job_queue_processes 或 min_parallel_servers 是否没有设置为过高的值,占用宝贵的内存)并将任何 oracle 实例参数设置为操作实例所需的值。
-
pga 报告中是否有大量 inactive 作业?
这表示有一些作业在任务完成时没有从数据库实例注销。
还要计算总 sga 和 pga 分配,并将其与物理内存大小进行比较。理想情况下,所有 oracle 内存都应适合物理内存,以防止发生过度交换。例如,如果定义了 6gb 的 sga,并且 pga 分配达到 4gb,并且服务器中安装了 12gb 的物理内存,那么只有 2gb 的内存可供操作系统和其他非 oracle 进程使用。这可能太小了,因此应该调查 sga 和/或 pga 是否为系统配置过大(基于交换统计数据,例如 vmstat 中看到的)。
pl/sql 呢?
当 pl/sql 为其集合类型(varrays、嵌套表等)分配内存时,该内存在 pga 工作区(例如排序区、散列区等)的外部,因此可能会超过实例的 pga_aggregate_target 设置。因此,此内存也会耗尽服务器上的可用内存。这是需要注意的。
自己的总结(回头来个脑图):
内存使用先看vmstat 是否有si so较高
ps aux |sort -rnk4|head 看哪些os进程高,如果是oracle的
oracle sga通常固定,pga需要用上面语句定位谁占用多
检查pga总量,检查当前oracle进程占用多少内存判断是否占用过多。
单个进程占用的诊断见上面的那堆oradebug...
没用的会话就断开,释放pga。
诊断一个进程pga是否在增长(确认是否发生内存泄漏)
-
column name format a25
-
column pname format a12
-
column "megabytes" format a10
-
set numwidth 6
-
-
select ss.sid, p.pid, p.pname, sn.name, round(ss.value/(1024 *1024))||'mb' "megabytes"
-
from v$sesstat ss, v$statname sn, v$session s, v$process p
-
where s.paddr = p.addr
-
and sn.statistic# = ss.statistic#
-
and s.sid = ss.sid
-
and sn.name in ('session pga memory' , 'session pga memory max')
-
and p.pname='dia0'
-
order by ss.value
-
/
如果经过1天后,再执行此语句,看到session pga memory在增加,那么就可以断定内存泄漏。
参考:
如何调查 unix/linux 服务器上的内存使用情况(文档 id 1447481.1)
阅读(1399) | 评论(0) | 转发(0) |