曾几何时,网络上流传着给Oracle数据库分配内存的一条法则:把80%的内存分配给Oracle使用,而又将这80%的内存分配80%给Oracle的SGA,剩下的20%分给Oracle的PGA。记得Tom曾说过类似这样的话:如果一个参数的设置对Oracle是最佳的,那么Oracle就会自动地将其设为了默认值。而显然,在内存分配这事上,Oracle的初始设置并不是按这个法则的,那么就是说从某一方面证明这个法则存在问题。

当然大部分DBA不会这样设置内存参数,但是也有不少的人在Oracle的内存分配上存在欠考虑的地方。

首先,我们来看看保留可用内存20%给操作系统是否合适。对于2G内存的服务器(现实中这样的机器不少),20%意味着400M,而通常400M对操作系统来说是不够用的。而对于内存特别多的主机,20%又显得太多。比如下面是一份来自于一台P595的内存情况:

====================================================|==========|===========
Memory Overview                                     |    Pages |  Megabytes 
----------------------------------------------------|----------|-----------
Total memory in system                              | 45875200 |  179200.00 
    Total memory in use                             | 34789026 |  135894.63 
    Free memory                                     | 11086174 |   43305.36 
====================================================|==========|===========
Segment Overview                                    |    Pages |  Megabytes 
----------------------------------------------------|---------|-----------
Total segment id mempgs                             | 32618956 |  127417.79 
    Total fork tree segment pages                   |     2074 |       8.10 
    Total kernel segment id mempgs                  |  3594452 |   14040.82 

这台主机共计179GB物理内存,已使用135G,其中内核占用14G。内核占用的内存不到总内存的10%。

以上的数据以及说明,只是表达这样一个观点,对于操作系统的保留内存,需要根据实际情况预以考虑,这包括了操作系统的内核参数的设置。比如在AIX下的默认设置,client和perm内存可以占用远远超过20%的内存,而HP-UX下的默认设置,File Cache和Buf Cache也可能占用远远超过20%的内存。所以对于这些环境的数据库,一定要注意调整OS的内核参数。对于OS的内存使用,至少保留20%也不失为一种稳妥的做法。

除了操作系统这一块,给Oracle分配内存的时候,还需要注意以下非常重要的几点,这几点经常被人忽略:

  • 注意业务高峰期的内存使用:我所维护的一套系统,平时的连接数通常在5000-5500左右,而在最高时连接数达到了8000,也就是到达了连接的上限才作罢。因此,我们需要为业务高峰期时保留足够的内存。
  • 对于RAC数据库,需要考虑到其他节点故障或停机维护时,连接和压力转移到继续工作的节点时的内存消耗。
  • 一些人只考虑到了连接时进程使用的PGA内存,这里存在一个很大的误解,就是认为一个连接,只会使用PGA的内存。但还有一个很重要的内存使用,那就是进程本身占用的操作系统内存,除了PGA之外的内存。进程本身有代码(在OS中这通常是共享的),有stack,有heap,还要有kernel的内存占用。PGA只是进程使用的内存中一部分,甚至大部分情况下只是一小部分。在Oracle 10.2.0.4 for AIX下测试过,一个空闲连接,也就是啥事儿都不干的一个连接,PGA占用500K左右,而server process进程占用的内存在4-5M之间。测试时这套库刚启动,没有任何负载。实际上据观察在一套运行比较长时间的库上,server process占用的内存在9-10M之间。当然不同的系统,不同的配置,oracle进程占用的内存有所不同,有兴趣的朋友可以测量一下Oracle进程在HP-UX和LINUX下的内存占用。

对于SGA内各组件的细分以及PGA大小设置,网上很多相关的文章可供参考,本文不再涉及。不过我的个人观点是:参数的调整也不是一步到位的事情,需要根据系统运行时对性能数据的分析来进行调整,直至达到最优化。

Trackback

14 comments untill now

  1. “参数的调整也不是一步到位的事情,需要根据系统运行时对性能数据的分析来进行调整,直至达到最优化。”非常赞同!

    [回复]

  2. 我在一次中粮面试中遇到256内存,分配sga和pga问题了,当时答的很差,没考虑到进程本身占用内存这点。
    我想问几个小问题:
    1.我怎么查看空闲连接时些pga占用多少内存?
    2.空闲连接时,server process占用多少内存?
    3.上面两个问题能否以v$pgastat或是v$process中看到的值为准,为什么?
    环境是rhle5 oracle 10.2.0.4单实例,如果您有时间帮解答下,谢谢!

    [回复]

    老熊 回复:

    @sunsyk,
    1.查pga占用可以从v$process里面查。
    2.空闲连接,进程的进程占用,可以用操作系统相关工具如pmap(aix上是procmap)来查看。
    3.上述2个值是不同的含义。特别是进程占用的一些内存,是在oracle视图中查不到的。

    [回复]

  3. 前些时间面试中粮时遇到一个问题256内存,oltp系统,并发3000,问如何分配sga和pga,当时回答很差,看这个帖子时发现进程本身所占内存没考虑。

    您帖子里有提到:
    在Oracle 10.2.0.4 for AIX下测试过,一个空闲连接,也就是啥事儿都不干的一个连接,PGA占用500K左右,而server process进程占用的内存在4-5M之间。
    我想知道这个是怎么测试出来?

    [回复]

    老熊 回复:

    @sunsyk,
    pga是从v$process中得到的。server process进程占用的内存用的是操作系统工具procmap。

    [回复]

  4. 多谢!

    [回复]

  5. 您好,有一些地方不明白,我负责的一个系统空闲连接PGA只占3M,但是server process却占用了100M,这是为什么呢,我查了很多个会话,server process基本都在90-150M之间,问题是我当时查看系统会话有2800多个,按每个进程100M就得280G的内存,实际上我的系统只有136G内存,这是怎么回事呢?多谢!

    [回复]

    老熊 回复:

    不知道你从哪个数据得到了server process占用了100M的结论。这里面肯定有共享内存部分,包括共享的代码,还有share memory的部分。要看server process占用的内存,只能看进程的private内存。

    [回复]

  6. 我是用下面的命令看的:
    $ps -ealf | head -1 ; ps -ealf | grep 2699382
    F S UID PID PPID C PRI NI ADDR SZ WCHAN STIME TTY TIME CMD
    240001 A oracle 2699382 1 3 61 20 38e9f45510 97792 11:32:32 – 0:04 oraclegzcrm1 (LOCAL=NO)

    $procmap 2699382
    2699382 : oraclegzcrm1 (LOCAL=NO)
    100000000 95477K read/exec oracle
    110000765 2399K read/write oracle
    9fffffff0000000 51K read/exec /usr/ccs/bin/usla64
    9fffffff000cfe2 0K read/write /usr/ccs/bin/usla64
    90000000074b5e0 2K read/exec /usr/lib/libC.a[shr3_64.o]
    9001000a020c5e0 0K read/write /usr/lib/libC.a[shr3_64.o]
    9000000006d3800 115K read/exec /usr/lib/libC.a[shrcore_64.o]
    9001000a0135400 12K read/write /usr/lib/libC.a[shrcore_64.o]
    90000000069bf80 112K read/exec /usr/lib/libC.a[ansicore_64.o]
    9001000a012b180 37K read/write /usr/lib/libC.a[ansicore_64.o]
    9000000024ae468 0K read/exec /usr/lib/libicudata.a[shr_64.o]
    9001000a0406468 0K read/write /usr/lib/libicudata.a[shr_64.o]
    9000000007563e8 2K read/exec /usr/lib/libC.a[shr2_64.o]
    9001000a020d3e8 0K read/write /usr/lib/libC.a[shr2_64.o]
    9000000004fd200 1552K read/exec /usr/lib/libC.a[ansi_64.o]
    9001000a020e800 269K read/write /usr/lib/libC.a[ansi_64.o]
    9000000003d6d00 134K read/exec /usr/lib/libC.a[shr_64.o]
    9001000a0139b00 19K read/write /usr/lib/libC.a[shr_64.o]
    9000000022fc180 1732K read/exec /usr/lib/libicuuc.a[shr_64.o]
    9001000a0407dac 180K read/write /usr/lib/libicuuc.a[shr_64.o]
    900000002087d80 2510K read/exec /usr/lib/libicui18n.a[shr_64.o]
    9001000a0435148 270K read/write /usr/lib/libicui18n.a[shr_64.o]
    900000000682180 91K read/exec /usr/lib/libsrc.a[shr_64.o]
    9001000a010e728 55K read/write /usr/lib/libsrc.a[shr_64.o]
    900000000418500 743K read/exec /usr/lib/liblvm.a[shr_64.o]
    9001000a013fe70 217K read/write /usr/lib/liblvm.a[shr_64.o]
    900000000732100 97K read/exec /usr/lib/libcorcfg.a[shr_64.o]
    9001000a0203448 18K read/write /usr/lib/libcorcfg.a[shr_64.o]
    9000000006b9b80 81K read/exec /usr/lib/libcfg.a[shr_64.o]
    9001000a0124490 26K read/write /usr/lib/libcfg.a[shr_64.o]
    90000000069a380 2K read/exec /usr/lib/libcrypt.a[shr_64.o]
    9001000a0102928 0K read/write /usr/lib/libcrypt.a[shr_64.o]
    900000001f50520 5K read/exec /usr/lib/libc.a[aio_64.o]
    9001000a0269228 0K read/write /usr/lib/libc.a[aio_64.o]
    9000000003f9880 119K read/exec /usr/lib/libodm.a[shr_64.o]
    9001000a0103688 40K read/write /usr/lib/libodm.a[shr_64.o]
    9000000004e2e00 102K read/exec /usr/lib/libperfstat.a[shr_64.o]
    9001000a02087b8 10K read/write /usr/lib/libperfstat.a[shr_64.o]
    900000001f4f000 0K read/exec /usr/lib/libdl.a[shr_64.o]
    9001000a0268000 0K read/write /usr/lib/libdl.a[shr_64.o]
    900000005ee9100 8636K read/exec /oracle/product/10.2.0/db/lib/libjox10.a[shr.o]
    8001000a0000b78 587K read/write /oracle/product/10.2.0/db/lib/libjox10.a[shr.o]
    9000000006f1000 257K read/exec /usr/lib/libpthreads.a[shr_xpg5_64.o]
    9001000a0177000 559K read/write /usr/lib/libpthreads.a[shr_xpg5_64.o]
    900000000000100 3923K read/exec /usr/lib/libc.a[shr_64.o]
    9001000a00004c0 1030K read/write /usr/lib/libc.a[shr_64.o]
    Total 121494K

    不知道您说的看进程的private内存,如何来看啊?多谢!

    [回复]

    老熊 回复:

    @老头, read/exec就是代码所占用的内存,这个是共享使用的,实际私有的内存是read/write部分,加在一起是5728K。

    [回复]

  7. 哦。。好的。。多谢大师指点啊

    [回复]

  8. 你好,我想问下,进程本身占用的操作系统内存,这部分内存算不算是sga里面的内存,还是和sga有重合?

    [回复]

    老熊 回复:

    进程本身占用的操作系统,跟SGA是没有重合的。

    [回复]

  9. 进程本身占用的操作系统内存,这部分内存是属于sga吗,还是额外的其它的内存

    [回复]

Add your comment now