Chinaunix首页 | 论坛 | 博客
  • 博客访问: 3688953
  • 博文数量: 715
  • 博客积分: 1860
  • 博客等级: 上尉
  • 技术积分: 7745
  • 用 户 组: 普通用户
  • 注册时间: 2008-04-07 08:51
个人简介

偶尔有空上来看看

文章分类

全部博文(715)

文章存档

2023年(75)

2022年(134)

2021年(238)

2020年(115)

2019年(11)

2018年(9)

2017年(9)

2016年(17)

2015年(7)

2014年(4)

2013年(1)

2012年(11)

2011年(27)

2010年(35)

2009年(11)

2008年(11)

分类: Oracle

2021-07-03 17:51:20


某测试库忽然非常慢,登上去都费劲,先看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 大小是以下两者中的较大者:

  • SGA_TARGET
  • SGA_MAX_SIZE


在自动内存管理 (AMM) 中 - 在 11g 中引入 - SGA 和 PGA 内存都包含在 MEMORY_TARGET 中,因此总内存占用将是较大的:

  • MEMORY_TARGET
  • MEMORY_MAX_TARGET

私有内存 - PGA

PGA 大小可以在 V$PGASTAT 中找到,详细信息可以在 V$PROCESS 中找到

  1. SGA 和分配的 PGA 之和就是 Oracle 内存使用量。
  2. 在 11g AMM 中, MEMORY_MAX_TARGET 定义了 SGA 和 PGA,Oracle 内存使用也是如此


所有 Oracle 进程都会有一部分 PGA 内存可以测量,而共享内存则无法测量,因为它被所有进程共享。


查找谁在使用内存的方法如下:

  1. 从 O/S 的角度来看,什么在使用内存?
  2. 从数据库的角度来看,什么在使用内存?
  3. 调和两种观点。

从 O/S 的角度来看,如何查看哪些进程正在使用内存?

使用 UNIX ps实用程序查看进程实际消耗了多少内存。例如,要获取按内存大小排序的前 50 个进程:


  1. Solaris: ps -eo user,pid,ppid,vsz,rss,time,comm | sort +4 -5 -n -r | head -50
  2. Linux: ps aux | sort +5 -6 -n -r | head -50
  3. AIX: ps aux | sort +5 -6 -n -r | head -50
  4. HP-UX: ps -elf | sort +9 -10 -n -r | head -50
内存大小不是绝对的,我们只使用这个输出来获得一个相对大小进行比较。

Oracle 进程是最大的内存消耗者。

从 Oracle 的角度来看,如何查看哪些进程正在使用内存?

为此,您可以查询 V$PROCESS:

  1. SET LINESIZE 120
  2. SET PAGESIZE 120
  3. COLUMN spid HEADING 'OSpid' FORMAT a8
  4. COLUMN pid HEADING 'Orapid' FORMAT 999999
  5. COLUMN sid HEADING 'Sess id' FORMAT 99999
  6. COLUMN serial# HEADING 'Serial#' FORMAT 999999
  7. COLUMN status HEADING 'Status' FORMAT a8
  8. COLUMN pga_alloc_mem HEADING 'PGA alloc' FORMAT 99,999,999,999
  9. COLUMN pga_used_mem HEADING 'PGA used' FORMAT 99,999,999,999
  10. COLUMN username HEADING 'Oracle user' FORMAT a12
  11. COLUMN osuser HEADING 'OS user' FORMAT a12
  12. COLUMN program HEADING 'Program' FORMAT a26


  13. select * from (
  14. SELECT p.spid,
  15.        p.pid,
  16.        s.sid,
  17.        s.serial#,
  18.        s.status,
  19.        round(p.pga_alloc_mem/1024/1024) alloc_m,
  20.        round(p.pga_used_mem/1024/1024) used_m,
  21.        s.username,
  22.        s.osuser,
  23.        s.program
  24. FROM v$process p, v$session s
  25. WHERE s.paddr( + ) = p.addr
  26. ORDER BY p.pga_alloc_mem DESC) where rownum<21;
前20个占用较多的会话。




PGA 的总使用量:

  1. 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,然后发出

  1. sqlplus /nolog
  2. CONNECT / AS SYSDBA
  3. ALTER SYSTEM SET max_dump_file_size=unlimited;
  4. ALTER SYSTEM SET EVENTS '10235 trace name context forever, level 65536';
  5. CONNECT / AS SYSDBA
  6. oradebug setospid
  7. oradebug unlimit
  8. oradebug dump errorstack 10
  9. oradebug dump heapdump 536870917
  10. oradebug tracefile_name -- This shows the location of the trace file generated
  11. oradebug close_trace -- This closes the trace file
  12. ALTER SYSTEM SET EVENTS '10235 trace name context off';
  13. 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是否在增长(确认是否发生内存泄漏)

  1. column name format a25
  2. column pname format a12
  3. column "MegaBytes" format a10
  4. set numwidth 6

  5. select ss.sid, p.pid, p.pname, sn.name, round(ss.value/(1024 *1024))||'Mb' "MegaBytes"
  6. from v$sesstat ss, v$statname sn, v$session s, v$process p
  7. where s.paddr = p.addr
  8. and sn.statistic# = ss.statistic#
  9. and s.sid = ss.sid
  10. and sn.name in ('session pga memory' , 'session pga memory max')
  11. and p.pname='DIA0'
  12. order by ss.value
  13. /
如果经过1天后,再执行此语句,看到session pga memory在增加,那么就可以断定内存泄漏。

参考:
如何调查 Unix/Linux 服务器上的内存使用情况(文档 ID 1447481.1)

阅读(1621) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~