目录
一、问题现象
alert.log日志有如下问题:
二、问题原因
1、由于PGA单个进程只能使用4GB大小限制导致Oracle 11g版本AUTO SQL TUNING遇到ORA-04030错误
从这里也可用看出这个错误是由AUTO SQL TUNING触发的,这个错误的原因是遇到了单个进程最多只能使用PGA只有4G的限制导致,下面是trace中的相关信息。
2、trace信息
可用看到,当前的PGA设置是50G,但是单个进程最多只能使用4G。 根据MOS文档PLSQL Procedure Causing ORA-04030: (pga heap,control file i/o buffer) And ORA-04030: (koh-kghu sessi,pmuccst: adt/record) or ORA-04030: (koh-kghucall ,pmucalm coll) Errors (文档 ID 1325100.1)的说明, 这是因为操作系统默认单个进程最多只能打开65530个内存映射条目限制的。
3、查看操作系统默认单个进程最多可以打开的内存映射条目数
[oracle@qdbzora:/home/oracle]$cat /proc/sys/vm/max_map_count 65530
4、数据库也有相对应的隐含参数_realfree_heap_pagesize_hint,默认是65536。
SQL> col NAME for a30 SQL> col VALUE for a20 SQL> col DESCRIB for a45 SQL> set lines 200 SQL> SELECT x.ksppinm NAME, y.ksppstvl VALUE,x.ksppdesc describ FROM SYS.x$ksppi x, SYS.x$ksppcv y WHERE x.indx = y.indx AND x.ksppinm LIKE '%realfree%';
_realfree_heap_pagesize_hin隐含参数的意思是realfree当前的分配大小是65536 bytes,也就是64K,也就对应操作系统上每个内存映射条目的内存大小是64K,而操作系统上又限制每个进程最多能打开65530个内存映射条目,因此,每个进程使用PGA就不能超过65536*55530≈4G。
三、解决方案
有两种解决方案,一种是调整操作系统单个进程打开内存映射条目的大小,另一种就是在数据库调整对应的分配单元大小
1、调整操作系统单个进程打开内存映射条目的大小
[oracle@qdbzora:/home/oracle]$vi /etc/sysctl.conf vm.max_map_count=262144
然后通过sysctl –p命令使之生效。这样每个映射条目大小64K,262144个条目就是16G,应该足够用了。
2、在数据库调整对应的分配单元大小
在数据库调整realfree的分配单元的大小,但是这个隐含参数是静态参数,需要重启数据库才能生效
SQL> alter system set "_realfree_heap_pagesize_hint"=262144 scope=spfile;
四、其他方式
以上两种方法,不管是修改操作系统的限制还是修改数据库的参数,只修改一个就可用,如果两种方法都修改,需要设置合理的值,避免单个进程使用的内存限制过大,万一有个进程出了问题,可能直接就把内存耗尽了。
对本案例来讲,还有一种解决方法,当然只对本案例有效,因为本案例ORA-04030错误是由于AUTO SQL TUNING导致的,而AUTO SQL TUNING对我来讲又没啥用,完全可用通过禁用AUTO SQL TUNING来解决这个问题。可用通过下马的方法关闭AUTO SQL TUNING。
BEGIN dbms_auto_task_admin.disable( client_name => 'sql tuning advisor', operation => NULL, window_name => NULL); END; /
如果需要开启AUTO SQL TUNING,可用通过下面的方法来开启。
BEGIN dbms_auto_task_admin.enable( client_name => 'sql tuning advisor', operation => NULL, window_name => NULL); END; /
针对单个进程只能使用4G的PGA导致的ORA-04030错误的问题,具体还要看是什么原因导致的,本案例特殊,由于是AUTO SQL TUNING触发的,而AUTO SQL TUNING对我这套数据库来讲并没什么用,所以可用通过禁用AUTO SQL TUNING的方式来解决,如果是业务程序的存储过程等PL/SQL导致的这个错误,就不能这样解决了,只能从上面的修改操作系统单个进程打开内存映射条目数或者修改数据库对应的每个映射条目内存分配大小来解决了。