某测试库忽然非常慢,登上去都费劲,先看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)
阅读(1621) | 评论(0) | 转发(0) |