如何精确的计算出PGA的大小(server process占用内存之和)

你知道如何计算真正的PGA么?
于是熟悉Oracle的大家会想到两种办法:
select value from v$pgastat where NAME='total PGA allocated';
或者
select sum(PGA_ALLOC_MEM) from v$process;
这两个值应该相当接近。
但是,事实是这样么?这两个视图是完全准确的么?
答案是否定的。这两个视图会少计算PGA。
让实验告诉我们为什么:
1. 在一个几乎完全idle的数据库上(dedicate mode),由动态视图显示其当前PGA为76M, 当前session数目为34;操作系统当前free memory为11143.6M。
select value/1024/1024  from v$pgastat where NAME='total PGA allocated'
union all
select sum(PGA_ALLOC_MEM)/1024/1024 from v$process
union all
select count(*) from v$session;
VALUE/1024/1024
---------------
     76.6796875
     76.6996403
             34
RAM       Avail 11143.6 Mb
2. 从远端写一个java多线程程序连接到数据库上,保持一定时间。(脚本最后attached--jdbc.java)
javac jdbc.java
java jdbc 200     -- open 200 sessions
3. 当session数目增长到261时,此时动态视图显示当前PGA为197M;操作系统当前free memory为10329.7 M。
SQL> /
VALUE/1024/1024
---------------
     197.273438
      197.44428
            261
RAM       Avail 10329.7 Mb
4. 由此可知,操作系统减少的内存为814M(11143-10329),但是由动态视图v$pgastat和v$process算出来的增加的PGA只有121M(197-76)。
所以,在此种情况下,动态视图明显少计算了很大一部分的PGA。

-----------------------------------------------------------
那么如何才能真正计算出PGA的大小呢?
在Solaris/unix上,可以使用pmap -x <pid>。
为什么不直接用pmap(pmap pid会快很多),而用pmap -x?
因为pmap -x才会计算出真正一个进程所独占的内存空间。
例如
> pmap -x 9041
9041:   oracleSID (DESCRIPTION=(LOCAL=NO)(SDU=8192))
(中间是具体每个mapped object所占的内存,省略)
         Address     Kbytes        RSS      Anon     Locked Mode   Mapped File
---------------- ---------- ---------- ---------- ----------
        total Kb   77014800   77005280      13096   76873808
这里,第四列Anon的总和就是这个进程所独占的内存,而不会包含SGA的那部分。

如果我们直接采用pmap pid的结果,取其[ heap ]+[ anon ]+[ stack ]之和来当做PGA是不准确的。
这里有两点原因:
1.这种方法计算出的pmap不包含一些lib的数据空间。
例如,我们通过pmap pid可以看到对同一个lib有两行内容:
FFFFFFFF7C100000         32K r-x--  /lib/sparcv9/librt.so.1
FFFFFFFF7C208000          8K rwx--  /lib/sparcv9/librt.so.1
其中第一行是代码部分,可以看到,是不能写的:r-x--  。
第二行时数据部分,是可写的:rwx--  
这里第二行的数据部分,其实应该归入PGA的计算中。
2.pmap pid显示出来的是虚拟内存,不仅仅包含RSS部分。
而pmap -x pid会分隔开RSS部分以及Anon部分,而我们关注的仅仅是Anon部分。
例如看看pmap -x pid和pmap的这个差别:
pmap -x pid:
         Address     Kbytes        RSS       Anon     Locked Mode   Mapped File
0000000106730000        832        192         64          - rwx--    [ heap ]
pmap pid:
0000000106730000        832K rwx--    [ heap ]
其实说这么多,大家只需记住pmap -x pid的结果对Anon的总和就是这个进程独占的内存空间,也就是PGA.

所以,随之而来的计算PGA的脚本也孕育而生,其实逻辑很简单:
1.找出所有process,除了后台进程(其实后台进程也应该算在PGA之内,但是由于在高并发环境下pmap -x 后台进程比较危险,而且也没多少后台进程,所以忽略不计)。
select spid from v$process where spid is not null and  background is null;
2.对每个进程pmap -x,计算出Anon的总和,也就是PGA。
pmap -x $eachprocess |grep "total" > tmpfile
cat tmpfile | awk '{sum+=$5;}END{print sum}'

在1000+个sessions的数据库上如此检测,会得到非常准确的PGA大小。
(当然,在执行脚本的过程中,如果有进程退出,那么pmap会找不到该进程,所以这样写脚本适合长连接。)
标签: 暂无标签
oraunix

写了 199 篇文章,拥有财富 1026,被 339 人关注

转播转播 分享分享 分享淘帖
回复

使用道具

P4 | 发表于 2012-4-29 13:42:29
这是个法宝啊,谢谢老师哦。。。。
回复

使用道具

P4 | 发表于 2012-9-15 13:48:55
顶顶顶顶顶顶顶顶顶顶
回复

使用道具

您需要登录后才可以回帖 登录 | 加入社区

本版积分规则

意见
反馈