有关ORA-04031的分析过程

一. ORA-04031的问题表现
当Oracle需要分配一个大对象到共享池中却无法找到一段连续可用的内存空间时候,通常会报:
04031, 00000, "unable to allocate %s bytes of shared memory ("%s","%s", "%s","%s")"
二. 涉及的参数

与共享池有关陈参数:

  1. SHARED_POOL_SIZE

    这个参数指定共享池的大小,以字节为单位。

  2. SHARED_POOL_RESERVED_SIZE

    指定为大的连续的共享池内存请求预留的共享池的大小。

  3. _SHARED_POOL_RESERVED_MIN_ALLOC

    这个参数是隐含参数,用于控制预留内存的分配。大于这个参数的内存分配可以使用预留内存的列表。这个参数的默认值适合 绝大多数的系统。

    可以通过执行如下SQL查到:
select nam.ksppinm NAME, 
val.KSPPSTVL VALUE   
from x$ksppi nam,x$ksppsv val 
where nam.indx = val.indx 
and nam.ksppinm like '%shared%' order by 1;

 

三. 可能的原因及处理措施

1. 共享池大小设置不合理

共享池大小是否合理,可首先确定library cache中是否缺乏连续的内存空间;

可以通过查询视图v$SHARED_POOL_RESERVED,满足如下的条件:
  • REQUEST_FAILURES>0
    AST_FAILURE_SIZE < SHARED_POOL_RESERVED_MIN_ALLOC
  • REQUEST_FAILURES=0
    LAST_FAILURE_SIZE < SHARED_POOL_RESERVED_MIN_ALLOC
如满足则说明SHARED_POOL_RESERVED_MIN_ALLOC设置过小
解决:增大到满足为止

2. 共享池碎片太多

如果是由于共享池碎片引起的ORA-04031错误,那么需要判断是由于library cache的碎片导致的还是共享池保留空间中的碎片太多导致的,判定规则:
  • REQUEST_FAILURES > 0
  • LAST_FAILURE_SIZE > SHARED_POOL_RESERVED_MIN_ALLOC

解决 :

  • 增大SHARED_POOL_RESERVED_MIN_ALLOC来减少对象被缓存到共享池保留空间中的数量
  • 增大SHARED_POOL_RESERVED_SIZE 和SHARED_POOL_SIZE来提高共享池保留空间中有更多可用的内存。

3. 大内存分配导致,报错信息如下:

ORA-04031: unable to allocate XXXX bytes of shared memory ("large pool","unknown object","session heap","frame")

当出现上述错误的时候,可以查看如下几个方面:

  • 检查V$SGASTAT看看多少的内存被使用和空闲:
SELECT pool,name,bytes FROM v$sgastat where pool = 'large pool';
  •  使用heapdump level 32来dump出大池heap,确定自由的块大小。

    从大池中分配的内存如果是LARGE_POOL_MIN_ALLOC 的块数倍可以避免产生碎片,任何请求要求分配的块大小如果小于LARGE_POOL_MIN_ALLOC,那么将分配 LARGE_POOL_MIN_ALLOC大小的内存。

解决:增大LARGE_POOL_SIZE的大小都有助于消除这个错误

4. Oracle bug

Oracle强烈建议安装最新的数据库补丁,大部分的ORA-04031错误都和BUGs相关,安装最新的补丁可以避免这些错误。报错有:
ORA-04031: unable to allocate bytes of shared memory ("shared pool","unknown object","joxlod: init h", "JOX: ioc_allocate_pal")

解决:关闭数据库,设置更大的JAVA_POOL_SIZE大小,错误中提及的共享池很容易误导认为是SGA内存消耗完全,此时不能去增大共享池大小,而应该是增大JAVA池的大小,然后重启数据库继续尝试。

5. 共享池碎片原因及视图

  1. 没有共享的SQL
  2. 执行了没有必要的软分析调用
  3. 没有使用绑定变量
根据造成共享池碎片的以上三个方面,对应用SQL进行有针对性的优化改造;为了捕获有问题的SQL,可通过以下视图进行分析:
  • V$SQLAREA视图,该视图保存了每个SQL和PL/SQL执行的块,具体查询脚本如下:
SELECT substr(sql_text,1,40) "SQL", 
count(*) , 
sum(executions) "TotExecs"   
FROM v$sqlarea 
WHERE executions < 5   
GROUP BY substr(sql_text,1,40) 
HAVING count(*) > 10   
ORDER BY 2;
  • X$KSMLRU视图:

    这个视图记录所有在共享池中由于分配自由空间而导致其他对象被刷新出共享池的信息。通常用来判定什么导致了大的自由空间分配。如果很多对象周期性的被刷新出共享池,那么会导致响应时间问题,例如libaray cache latch的竞争问题。

    尤其需要注意的是当存储了最大的自由空间分配之后,任何时候查询这个视图都会删除这个视图中的内容,即使下一个分配的大的自由空间没有以前的大,这些被查询的值都会被重置,因此,查询这个表的结果应该被小心的保存下来。

监控这个视图只需要运行下面的SQL:(SYS用户)

SELECT * FROM X$KSMLRU WHERE ksmlrsiz > 0;

 

来源:IT那活儿,本文观点不代表自营销立场,网址:https://www.zyxiao.com/p/128200

发表评论

登录后才能评论
侵权联系 投诉举报
返回顶部