1、PGA的结构
Oracle的内存结构,除了SGA(System Global Area)之外,Oracle进程还使用下面三个全局区:
The Process Global Area (PGA)
The User Global Area (UGA)
The Call Global Area (CGA)
[@more@] 很多人都搞不清楚PGA和UGA两者之间的区别,实际上两者之间的区别跟一个进程和一个会话之间的区别是类似的.尽管说进程和会话之间一般都是一对一的关系,但实际上比这个更复杂.一个很明显的情况是MTS配置,会话往往会比进程多得多.在这种配置下,每一个进程会有一个PGA,每一个会话会有一个UGA.PGA所包含的信息跟会话是无任何关联的,而UGA包含的信息是以特定的会话为基础的 .1.1 PGA (Program Global Area)
进程全局区(PGA)即可以理解为Process Global Area,也可以理解为Program Global Area.它的内存段是在进程私有区(Process Private Memory)而不是在共享区(Shared Memory).它是个全局区意味着它包含了所有代码有可能进入的全局变量和数据结构,但是它是不被所有进程共享的.每个Oracle的服务器进程都包含有属于自己的PGA,它只包含了本进程的相关特定信息.PGA中的结构不需要由latches来保护,因为其它的进程是不能进入到这里面来访问的.
PGA包含的是有关进程正在使用的操作系统资源信息以及进程的状态信息,而其它的进程所使用的Oracle的共享资源是在SGA中.PGA是私有的而不是共享的,这个机制是有必要的,因为当进程死掉后可以把这些资源清除和释放掉.
PGA包含两个主要区域:Fixed PGA和Variable PGA或称为PGA Heap. Fixed PGA的作用跟Fixed SGA是类似的,都包含原子变量(不可分的),小的数据结构和指向Variable PGA的指针.
Variable PGA是一个堆.它的Chunks可以从Fixed Table X$KSMPP查看得到,这个表的结构跟前面有提到的X$KSMSP是相同的.PGA HEAP包含了一些有关Fixed Table的永久性内存,它跟某些参数的设置有依赖关系.这些参数包含DB_FILES,LOG_FILES,CONTROL_FILES.
1.2 UGA (User Global Area)
UGA(User Global Area)包含的是特定会话的信息,有如下一些:
所打开游标的持续和运行时间内的区域
包的状态信息,特定的变量
Java会话状态
可以用的ROLES
被ENABLE的跟踪事件
起作用的NLS参数设置
打开的DBLINK
会话的入口控制
跟PGA一样,UGA也由两区组成:Fixed UGA和Variable UGA,也称为UGA HEAP. Fixed UGA包含了大约70个原子变量,小的数据结构和指向Variable UGA的指针.
UGA HEAP中的Chunks可以从它们自己的会话中通过查看表X$KSMUP获得相关信息,这个表的结构跟X$KSMSP是一样的.UGA HEAP包含了一些有关fixed tables的永久性内存段,跟一些参数的设置有依赖关系.这些参数有OPEN_CURSORS,OPEN_LINKS,和MAX_ENABLE_ROLES.
UGA在内存中的位置依赖于会话的配置方式.如果会话连接的配置方式是专用服务器模式(DDS)即是一个会话对应一个进程,则UGA是放在PGA中的.在PGA中,Fixed UGA是其中的一个Chunk,而UGA HEAP是PGA的一个子堆(Subheap).如果会话连接是配置为共享服务器模式(MTS), Fixed UGA是SHARED POOL中的一个Chunk,而UGA HEAP则是SHARED POOL中的子堆(Subheap)
1.3 CGA (Call Global Area)
跟其它的全局区不同,Call Global Area是短暂性存在的.它只有在调用数据期间存在,一般是在对实例的最低级别的调用时才需要CGA,如下:
分析一个SQL语句
执行一个SQL语句
取出一个SELECT语句的输出
一个单独的CGA在递归调用时是需要的.在SQL语句的分析过程中,对数据字典信息的递归调用是需要的,因为要对SQL语句进行语法分析,还有在语句的优化期间要计算执行计划.执行PL/SQL块时在处理SQL语句的执行时也是需要递归调用的,在DML语句的执行时要处理触发器执行也是需要递归调用的.
不管UGA是放在PGA中还是在SGA中,CGA都是PGA的一个子堆(Subheap).这个事实的一个重要推论是在一个调用的期间会话必须是一个进程.对于在一个MTS的Oracle数据库进程应用开发时关于这一点的理解是很重要的.如果相应的调用较多,就得增加processes的数量以适应调用的增加.
没有CGA中的数据结构,CALLS是没法工作的.而实际上跟一次CALL相关的数据结构一般都是放在UGA中,如SQL AREA,PL/SQL AREA和SORT AREA它们都必须在UGA中,因为它们要在各CALLS之间要一直存在并且可用.而CGA中所包含的数据结构是要在一次CALL结束后能够释放的.例如CGA包含了关于递归调用的信息,直接I/O BUFFER等还有其它的一些临时性的数据结构.
Java Call Memory也是在CGA中.这一段内存比Oracle的其它内存段管理得更密集.它分成三个Space: Stack Space, New Space, Old Space.在New Space和Old Space中不再被参考使用的Chunks,根据它们在使用期间的长度及SIZE的不同,在调用的执行过程中将被当成不用的Chunks收集起来.New Space Chunks很多次的不用的Chunks的反复收集过程中没有被收集的Chunks将会被放到Old Space Chunks中.这是在Oracle内存管理中唯一的一个废物收集(garbage collection),其它的Oracle内存段都是释放Dead Chunks.
下面这幅图表现了共享服务器模式和专用服务器模式下,PGA、UGA的不同情况:
2、PGA内存的分配与回收
2.1 Process Memory Allocation
跟SGA不一样的是,SGA在实例启动之后SIZE就已经是定下来的,而PGA的SIZE是会增长的.通过使用malloc()或者sbrk()系统调用来为进程增加堆数据段大小而使得PGA的SIZE的增长.OS的新虚拟内存会被做为PGA HEAP中的一个新的区被加到PGA中来.这些区一般只几KB大,如果有需要,Oracle将会给分配上千个区.
操作系统对每个进程的堆数据段的增长是有限制的.大部分的情况是操作系统的内存参数进行限制(kernel parameter: MAXDSIZ),有一些情况它的缺省值是可以以每个进程为基准进行修改的.对于所有的进程,操作系统对整个虚拟内存也有一个系统全局性的限制,这个限制跟系统的SWAP SPACE相关.一旦超过了这两个限制,Oracle的进程在执行中会遇到ORA-4030错误.
ORA-4030这个错误的产生一般不是因为每个进程的资源限制而是因为SWAP SPACE空间不足造成.为了诊断这个问题可以使用操作系统的一些选项来查看SWAP SPACE的使用情况.另外,在一些操作系统中,Oracle包含了一个工具叫maxmem,它可以用来查看每个进程可以被分配的堆数据段的最大SIZE以及哪一个限制是第一次超过的.
如果这个问题的出现是因为SWAP SPACE空间不足,而且换页的动作非常频繁而且较多,则需要减少系统一级的虚拟内存的使用,这个可以通过减少进程数也可以通过减少每个进程的内存限制.如果换页动作不频繁而且比较少,则需要调大SWAP SPACE SIZE.
2.2 Process Memory Deallocation
Oracle堆的增长比它们的收缩要来得容易,当然它们的SIZE也是可以收缩的.在V$MYSTAT和V$SESSTAT视图中,session的统计信息session uga memory和session pga memory分别显示了当前session的UGA和PGA的内存大小,包含内部的空闲空间.相应的统计信息session uga memory max 和 session pga memory max分别显示了在session的生存期间所使用过得最大的UGA和最大的PGA.
UGA和PGA只有在特定的操作后才会收缩,这些操作如一次磁盘排序的合并操作,或者用程序DBMS_SESSION.FREE_UNUSED_USER_MEMORY显示释放内存.只有整个free heap extent会被释放给父堆或者是进程堆数据段,所以有一部分的内部free space在内存释放后仍然存在于subheap中.
在大多的操作系统环境下,Oracle是不会减少进程堆数据段也不会释放虚拟内存并将其返还给操作系统的.所以从一个操作系统的查看中,一个Oracle的进程将会把虚拟内存SIZE作为HWM而保留着.如果有必要时,Oracle是会将一些没用的虚拟内存页换页出去的.因为这个原因,有关Oracle进程的虚拟内存页的操作系统统计信息都是很难理解的.所以一般用的是Oracle内部统计信息来代替使用操作系统的统计信息.
程序DBMS_SESSION.FREE_UNUSED_USER_MEMORY只能在连接是配置为MTS模式的应用才能使用.这个最好是少点使用,因为它只释放大的包的array变量所占用的内存返还给Large Pool或者是Shared Pool.一般地,UGA HEAP的内存应该首先被释放,可以通过指派新的空array给array变量使用,也可以通过调用程序DBMS_SESSION.RESET_PACKAGE.
3、Oracle9i中的PGA自动管理
Oracle9i之前的PGA管理,需要手工设置HASH_AREA_SIZE/SORT_AREA_SIZE等参数,每个连接所占用的PGA大概为:
UNIX: 1M+HASH_AREA_SIZE+SORT_AREA_SIZE
WINDOWS: 2M+HASH_AREA_SIZE+SORT_AREA_SIZE
其中1M、2M分别为在unix和windows下的os所占用的内存,用该值乘上估算的连接可以大致计算出所有连接PGA所占用的内存空间。
在Oracle9i中提供了自动管理PGA的新特性,可以自动并动态的在各个Session之间调整内存分配。PGA可以分类分为可调整和非可调整,可调整内存主要用于DSS系统中。
3.1 跟PGA相关的初始化参数
A.WORKAREA_SIZE_POLICY 可选值为’AUTO’和’MANUAL’,默认值’AUTO’
设置为MANUAL,PGA的分配和管理与之前的数据库版本一致。设置为AUTO则使用9i的新特性自动管理PGA。
B.PGA_AGGREGATE_TARGET
默认值为25M,如果WORKAREA_SIZE_POLICY设置为AUTO,该值定义最大可用的PGA内存。
3.2 确定PGA_AGGREGATE_TARGET的大小
A.估算:
对于OLTP系统 : PGA_AGGREGATE_TARGET = ( * 80%) * 20%
对于DSS系统 : PGA_AGGREGATE_TARGET = ( * 80%) * 50%
这种估算基于80%内存用于Oracle,其中对于OLTP系统有20%用于PGA,而对于DSS系统有50%用于PGA。
B.使用视图v$pga_target_advice的建议值
3.3 通过动态性能视图监控PGA的使用
1) V$PGASTAT:该视图提供了实例级别上PGA内存使用的统计信息。
下面是对其中一些统计值的解释:
aggregate PGA auto target :该列是Oracle9i连接的可用内存总数,来源于init.ora转念馆参数pga_aggregate_target
global memory bound :改统计量测量了一个工作区的最大尺寸,并且Oracle推荐只要该统计量低于1M时,就应该增加pga_aggregate_target的值。
total PGA allocated :该统计量显示了数据库上所有PGA内存使用的最高标准。当使用增加时,该值会接近pga_aggregate_target的值。
total PGA used for auto workarea :该统计量监控正在以自动内存模式运行的所有连接的RAM消耗。记住,Oracle并不是允许所有内部进程都使用自动内存功能。例如,Java和PL/SQL将分配RAM内存,但并不计入整个PGA统计量中。因此,你可以减去已分配的PGA的值,以查看连接占用的内存数量以及Java和PL/SQL消耗的RAM内存。
estimated PGA memory for optimal/one-pass :该统计量估计在最优模式下需要多少内存来执行所有任务连接的RAM需求。记住,当Oracle9i经历内存短缺时,Oracle9i将调用多通道操作,以努力查找最近空闲的RAM内存的位置。该统计量对监控Oracle9i中的RAM消耗是重要的,并且大多数Oracle DBA将增加pga_aggregate_target达到该值。
2) 视图v$sql_workare_active显示实例中当前正在执行的所有工作区
以下查询显示实例中活动的工作区域的使用情况,但低于64K的排序操作在该视图中不会显示。
SELECT to_number(decode(SID, 65535, NULL, SID)) sid,operation_type OPERATION,trunc(EXPECTED_SIZE/1024) ESIZE,
trunc(ACTUAL_MEM_USED/1024) MEM, trunc(MAX_MEM_USED/1024) "MAX MEM",
NUMBER_PASSES PASS, trunc(TEMPSEG_SIZE/1024) TSIZE
FROM V$SQL_WORKAREA_ACTIVE
ORDER BY 1,2
3) 视图v$sysstat中包含启动数据库实例后,工作区以三种模式执行的时间总数
SELECT name,value FROM v$sysstat WHERE name like 'workarea exec%';
optimal: workarea execution of which all processes such as sort are executed on memory
onepass: workarea execution that requires the minimum writes to a disk
multipass: workarea execution that requires heavy writes to a disk because SQL workarea is too low
4、可选的客户端连接方式
如果服务器是专用服务器模式,那么客户端只能以DEDICATED方式连上数据库;如果服务器是共享服务器模式,则客户端可以通过修改tnsnames.ora文件中的配置参数server来改变与数据库的连接方式:DEDICATED或SHARED。例如:
-----------tnsnames.ora begins---------------
#MTS
ORADB1 =
(DESCRIPTION =
(ADDRESS_LIST =
(ADDRESS = (PROTOCOL = TCP)(HOST = 192.168.1.1)(PORT = 1521))
)
(CONNECT_DATA =
(SERVICE_NAME = oradb)
(SERVER = SHARED)
)
)
#DEDICATED
ORADB2 =
(DESCRIPTION =
(ADDRESS_LIST =
(ADDRESS = (PROTOCOL = TCP)(HOST = 192.168.1.1)(PORT = 1521))
)
(CONNECT_DATA =
(SERVICE_NAME = oradb)
(SERVER = DEDICATED)
)
)
--------------tnsnames.ora ends----------------
当客户端使用ORADB1连接一个共享服务器时,UGA在共享池中,排序发生在共享池中;当客户端使用ORADB2连接一个共享服务器时,UGA在PGA中,排序发生在PGA中。会话的间接模式可以从V$SESSION中的字段server获得:
5、Undocumented PGA
本节主要研究带排序的SQL语句每次执行时所能使用的最大PGA内存是由哪些参数来控制的。以下测试都是基于专用服务器模式的,共享服务器模式的本节暂不考虑,Oracle9.2.0.6 for Linux ,RAM 4G。相关系统参数:
SQL>select ksppinm, ksppstvl, ksppdesc from x$ksppi x, x$ksppcv y
where x.indx = y.indx and ksppinm in
('_pga_max_size','_smm_max_size','_smm_px_max_size','pga_aggregate_target');
KSPPINM KSPPSTVL KSPPDESC
---------------- --------- ------------------------------------------------------------
pga_aggregate_target 41943040 Target size for the aggregate PGA memory consumed by the instanc
_pga_max_size 209715200 Maximum size of the PGA memory for one process
_smm_max_size 2048 maximum work area size in auto mode (serial)
_smm_px_max_size 12288 maximum work area size in auto mode (global)
其中,_smm_max_size和_smm_px_max_size的单位是KB,其它都是Byte,_pga_max_size缺省值是200M。
当你设置参数pga_aggregate_target时,Oracle系统会根据pga_aggregate_target和_pga_max_size这两个值来自动修改参数_smm_max_size,根据 pga_aggregate_target修改_smm_px_max_size,具体规则如下:
<1> When _pga_max_size > 5% of pga_aggregate_target, then _smm_max_size = 5% of pga_aggregate_target
<2> When _pga_max_size <= 5% of pga_aggregate_target, then _smm_max_size = 50% of _pga_max_size
<3> _smm_px_max_size = 30% of pga_aggregate_target
注意:你可以手工修改_smm_max_size和_smm_px_max_size,但Oracle不支持用户这样做。
5.1 非并行查询
对于非并行查询来说,单条sql语句所能用到的PGA内存最大值由以下公式决定:
MIN(pga_aggregate_target,50%*_pga_max_size,_smm_max_size)
在网上经常可以看到有些资料说取MIN(pga_aggregate_target*5%,100M),这种情况没有考虑直接修改隐藏参数_smm_max_size、 _pga_max_size(缺省200M)的情况,在这两个参数不进行人工修改的情况下,这个式子才成立。
下面给出一个测试的结果表,每次sql完毕后查询其使用的最大内存所用sql如下(为了保证使用了最大内存,每次结果中NUMBER_PASSES>0,TEMPSEG_SIZE>0):
SQL>select t.OPERATION_TYPE,t.SID,t.WORK_AREA_SIZE,t.ACTUAL_MEM_USED,
t.MAX_MEM_USED,t.NUMBER_PASSES,t.TEMPSEG_SIZE
from v$sql_workarea_active t;
其中MAX_MEM_USED就是该sql曾经使用到的最大内存
使用以下语句在SYS下修改参数,注意这些参数只能在system level修改,不能在session level进行修改:
SQL> alter system set "pga_aggregate_target"="256m";
SQL> alter system set "_pga_max_size"="30m";
SQL> alter system set "_smm_max_size"=10240;
生成测试数据:
SQL> cretae table test as select * from dba_objects where rownum <= 20000;
SQL> insert into test select * from test;
........ 反复多次,直到数据量有512万
SQL> select * from test order by 1,2,3,4,5,6,7,8,9,10;
pga_aggregate_target | _pga_max_size | _smm_max_size | 单条SQL实际使用最大内存 |
256M | 30M | 10M | 9.72M |
256M | 30M | 10M | 9.72M |
256M | 30M | 20M | 15.66M |
256M | 50M | 50M | 27.78M |
256M | 100M | 50M | 49.24M |
256M | 200M | 150M | 105.60M |
256M | 300M | 200M | 154.63M |
256M | 400M | 300M | 187.10M |
256M | 500M | 300M | 226.41M |
256M | 1200M | 500M | 273.96M |
400M | 1200M | 500M | 401.13M |
512M | 1200M | 500M | 485.37M |
700M | 1200M | 700M | 587.31M |
750M | 1400M | 750M | 710.65M |
800M | 1200M | 800M | 710.65M |
900M | 1200M | 900M | 710.65M |
900M | 1800M | 900M | 734.86M |
5.2 并行查询
对于并行查询来说,情况要更加复杂一些,主要是对于所有的从属进程(slave)来说,它们所使用的内存有个上限,就是隐藏参数_smm_px_max_size值。缺省情况下,当你只设置pga_aggregate_target值时,系统会同时配置_smm_px_max_size,使其等于30%*pga_aggregate_target。
简单来说,对于并行查询中的每个slave process,其能使用的最大内存为:
MIN(pga_max_size/2,_smm_max_size,_smm_px_max_size/degree) degree是查询时的并行度
Don Burleson有篇文章《Undocumented secrets for super-sizing your PGA》讲到了并行查询下参数_smm_px_max_size的作用,但是他没有考虑到参数_smm_max_size对每个进程内存的限制作用,因此他的结论也是有问题的,对此Jonathan Lewis和Tom Kyte都指出了其错误。另外,在我的测试中,我还发现这个最大值跟pga_max_size*50%也是有关系的。
参考资料:
<1> http://www.pythian.com/documents/Working_with_Automatic_PGA.ppt
<2> http://www.performance-insight.com/html/ora3/back/sort_1.html
<3> Don Burleson:Undocumented secrets for super-sizing your PGA
<4> Jonathan Lewis: http://www.jlcomp.demon.co.uk/untested.html http://www.jlcomp.demon.co.uk/snark.html#Addendum
<5> Tom Kyte:
http://tkyte.blogspot.com/2005/08/getting-credible-information.html#c112495300113904568 http://asktom.oracle.com/pls/ask/f?p=4950:8:::::F4950_P8_DISPLAYID:47466211228419
<6> Wanghai blog: http://spaces.msn.com/members/wzwanghai/PersonalSpace.aspx?_c01_blogpart=my
来自 “ ITPUB博客 ” ,链接:http://blog.itpub.net/3898/viewspace-807263/,如需转载,请注明出处,否则将追究法律责任。
转载于:http://blog.itpub.net/3898/viewspace-807263/