(ORA-04031)-Oracle在分配内存空间时错误
现象描述
ORA-04031,"unable to allocate %s bytes of shared memory (\"%s\",\"%s\",\"%s\",\"%s\")"
可能原因
- Oracle在分配java pool、shared pool或large pool的空间时,没有找到足够的连续空闲空间导致系统报ORA-04031错误。
- ORA-4031错误提示是shared pool无足够连续内存可分配时,可能是由于shared pool不足或者shared pool中严重的碎片导致。
定位思路
- Oracle Bug:
大部分的ORA-04031错误都和Bug(例如Bug 6271680、Bug 5705795、Bug 5548510、Bug 5552515等)相关。
- java pool不足:当编译Java代码(包括loadjava),内存消耗完之后会出现如下错误(不要将错误中提及的共享池误认为是SGA内存消耗问题):
ORA-04031: unable to allocate %s bytes of shared memory ("shared pool","unknown object","joxlod: init h", "JOX: ioc_allocate_pal") - shared pool不足:在多数情况下,使用以下的方法来帮助定位,是否是共享池过小导致ORA-04031错误。
- 使用Library Cache命中率帮助判断共享池的设置是否合理。
计算library cache命中率的SQL语句如下:
select sum(a.value)/count(*) pct
from v$metric_history a
where a.metric_name = 'Library Cache Hit Ratio'
and group_id = 2
and a.begin_time >= sysdate - 1
and a.end_time < sysdate;
如果命中率小于99%,则是共享池过小导致ORA-04031错误。
- 参考AWR报表中的Shared Pool Advisory,评估shared pool是否设置得足够大。
- 查询V$SHARED_POOL_ADVICE视图,获得关于Shared pool的建议信息。
- 使用Library Cache命中率帮助判断共享池的设置是否合理。
- shared pool碎片:每当载入library cache中分析一个SQL或PL/SQL时,都需要一定数量的连续自由空间。当自由空间耗尽时,数据库会寻找并重新使用一个已经分配过的但当前不使用的空间。Oracle寻找连续自由空间的标准如下:
- 可用块大小大于需要的大小。
- 可用块空间是连续的。
- 可用块当前不在使用中。
Oracle寻找到的可用块将被分割,而剩余的自由空间将加入到正确的自由空间列表中。当数据库这样运行一段时间后,导致共享池结构被碎片化。当共享池中碎片情况比较严重时,以后每次分配自由空间都需要更长时间(由共享池的latch来控制),导致整个数据库性能下降,并引起ORA-04031错误。
如果共享池已经设置的足够大,并且非Oracle Bug导致错误,则大部分ORA-04031错误都是由于共享池中的动态SQL碎片引起的:- 没有共享的SQL。
- 执行了没有必要的软分析调用。
- 应用程序中存在未使用绑定变量的语句,导致大量的硬解析。
查找未使用绑定变量的SQL语句,命令如下:
SELECT substr(sql_text,1,40) "SQL",
count(*)
FROM v$sqlarea
GROUP BY substr(sql_text,1,40)
HAVING count(*) > 30
ORDER BY 2;
说明: - 40表示一个SQL语句至少前40个字符是相同的。
- 30表示前40个字符相同的SQL语句至少存在30条以上。
- 现场可根据应用的特点,调整40和30为其他数值。
- large pool(大池)不足:大池是一个可选的内存区域,能够为下列操作提供大内存分配:
- 针对多线程服务器和OracleXA接口的会话内存。
- 针对Oracle RMAN备份和恢复操作所需要的内存。
- 并行执行的信息缓存。
大池没有LRU列表,它和共享池中的保留空间不太一样,大池中的内存块永远不会刷新出去,它针对每一个会话明确的分配和释放内存。
如果大池中没有自由内存空间,而又有请求,则会出现类似下面的ORA-04031错误。ORA-04031: unable to allocate XXXX bytes of shared memory ("large pool","unknown object","session heap","frame")需要查找被使用和空闲的内存的命令如下:
SQL> SELECT pool,name,bytes FROM v$sgastat where pool = 'large pool';
处理步骤
- 使用Oracle实用程序oerr,查询ORA-04031错误信息的说明。
$ oerr ora 4031
显示信息样例如下:// *Cause: More shared memory is needed than was allocated in the shared // pool. // *Action: If the shared pool is out of memory, either use the // DBMS_SHARED_POOL package to pin large packages, // reduce your use of shared memory, or increase the amount of // available shared memory by increasing the value of the // initialization parameters SHARED_POOL_RESERVED_SIZE and // SHARED_POOL_SIZE. // If the large pool is out of memory, increase the initialization // parameter LARGE_POOL_SIZE.
- 根据报错的说明,结合如表1所示方法,处理故障。
表1 不同类型的ORA-04031错误处理步骤说明表 ORA-04031错误类型
处理方法
Oracle Bug
- 安装最新的数据库补丁。
- 如果以上方法不能解决问题,请向Oracle Support提SR单请求支持,上传相应的trace文件以确定是否是Oracle Bug导致。
shared pool碎片
在服务器端连接数据库。
sqlplus / as sysdba
如果此时报ORA-04031错误,则重启数据库。如果重启数据库后,问题还没有解决,并且严重影响了业务,请收集信息相关后,并向Oracle Support提SR单请求支持。
- 清除共享池中的内容,重新格式化内存。注意:
此方法仅是临时处理方法。此操作会引起SQL的重解析,重解析时会引起严重的性能问题。请根据客户的应用与客户讨论是否能运行此命令。
SQL> alter system flush shared_pool;
java pool不足
根据不同的情况,增大对应的pool大小。- 如果是java pool不足,则增大参数“java_pool_size”。
- 如果是shared pool不足,则增大参数“shared_pool_size”。
- 如果是large pool不足,则增大参数“large_pool_size”。
shared pool不足
large pool不足




