暂无图片
暂无图片
暂无图片
暂无图片
暂无图片

(ORA-04031)-Oracle在分配内存空间时错误

原创 huawei 2021-03-02
4506

(ORA-04031)-Oracle在分配内存空间时错误

现象描述

系统出现ORA-04031错误,并伴随具体的报错参数,如下所示:
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的建议信息。
  • 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';

处理步骤

  1. 使用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.
  2. 根据报错的说明,结合如表1所示方法,处理故障。

    表1 不同类型的ORA-04031错误处理步骤说明表

    ORA-04031错误类型

    处理方法

    Oracle Bug

    1. 安装最新的数据库补丁。
    2. 如果以上方法不能解决问题,请向Oracle Support提SR单请求支持,上传相应的trace文件以确定是否是Oracle Bug导致。

    shared pool碎片

    1. 在服务器端连接数据库。

      sqlplus / as sysdba

      如果此时报ORA-04031错误,则重启数据库。如果重启数据库后,问题还没有解决,并且严重影响了业务,请收集信息相关后,并向Oracle Support提SR单请求支持。

    2. 清除共享池中的内容,重新格式化内存。
      注意:

      此方法仅是临时处理方法。此操作会引起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不足

「喜欢这篇文章,您的关注和赞赏是给作者最好的鼓励」
关注作者
【版权声明】本文为墨天轮用户原创内容,转载时必须标注文章的来源(墨天轮),文章链接,文章作者等基本信息,否则作者和墨天轮有权追究责任。如果您发现墨天轮中有涉嫌抄袭或者侵权的内容,欢迎发送邮件至:contact@modb.pro进行举报,并提供相关证据,一经查实,墨天轮将立刻删除相关内容。

评论