ORA04031

错误现象:

ORA-00604:递归SQL级别3出现错误
ORA-04031:无法分配4096字节的共享内存("shared pool","select /*+ rule */bucket_cn...","Typecheck heap","kgghteInit")


错误原因:
通过
Select * from v$sgastat
where pool ='shared pool' and upper(name) like '%FRE%'
or upper(name) like '%MISC%';

查询出shared pool miscellaneous 的值较大

解决方法:

1.修改init<SID>.ora 文件,增加  "_db_handles_cached = 0" 然后重启服务。
2.init<SID>.ora 文件,可能为  D:\oracle\product\10.1.0\admin\lcsoft\pfile\init.ora.320201211837

或者 修改值
shared_pool_size         = 200M
db_cache_size            = 600M

--------------------------------------------------------------------------------------------------------------------------------------------------

一、错误信息: 

EXP-00008: ORACLE error 4031 encountered
 ORA-04031: unable to allocate 4096 bytes of shared memory
 ("shared pool","BEGIN :EXEC_STR := SYS.DBMS...","PL/SQL MPCODE","BAMIMA: Bam Buffe
  
  二、错误原因:
  共享内存太小,存在一定碎片,没有有效的利用保留区,造成无法分配合适的共享区。
  
  三、解决步骤:
  1.查看当前环境
  SQL>  show sga
  
  Total System Global Area 566812832 bytes
  Fixed Size          73888 bytes
  Variable Size       28811264 bytes
  Database Buffers     536870912 bytes
  Redo Buffers        1056768 bytes
  
  show parameter shared_pool
  NAME                 TYPE  VALUE
  ------------------------------------ ------- -----
  shared_pool_reserved_size      string 1048576
  shared_pool_size           string 20971520
  
  SQL> select sum(free_space) from v$shared_pool_reserved;
  
  SUM(FREE_SPACE)
  ---------------
  1048576
  
  我们可以看到没有合理利用保留区
  
  SQL> SELECT SUM(RELOADS)/SUM(PINS) FROM V$LIBRARYCACHE;
  
  SUM(RELOADS)/SUM(PINS)
  ----------------------
  .008098188
  
  不算太严重
  SQL> SELECT round((B.Value/A.Value)*100,1) hardpaseperc
  FROM V$SYSSTAT A,
  V$SYSSTAT B
  WHERE A.Statistic# = 171
  AND B.Statistic# = 172
  AND ROWNUM = 1;
  
  hardpaseperc
  ------------------
  26.5
  
  2.查看保留区使用情况
  SQL>  SELECT FREE_SPACE,
  FREE_COUNT,
  REQUEST_FAILURES,
  REQUEST_MISSES,
  LAST_FAILURE_SIZE
  FROM V$SHARED_POOL_RESERVED;
  
  FREE_SPACE FREE_COUNT REQUEST_FAILURES REQUEST_MISSES LAST_FAILURE_SIZE
  ---------- ---------- ---------------- -------------- -----------------
  1048576     1       146       0       4132
  
  最近一次申请共享区失败时该对象需要的共享区大小4132
  
  select name from v$db_object_cache where sharable_mem = 4132;
  name
  ----------------
  dbms_lob
  
  -- dbms_lob正是exp时申请保留区的对象
  3.查看导致换页的应用
  SQL> select * from x$ksmlru where ksmlrsiz>0;
  
  ADDR   INDX  INST_ID KSMLRCOM   KSMLRSIZ KSMLRNUM KSMLRHON KSMLROHV KSMLRSES
  
  50001A88 0     1 BAMIMA: Bam Buffer 4100     64 DBMS_DDL 402745060 730DEB9C
  
  50001ACC 1     1 BAMIMA: Bam Buffer 4108    736 DBMS_SYS_SQL 1909768749 730D0838
  
  50001B10 2     1 BAMIMA: Bam Buffer 4112    1576 STANDARD 2679492315 730D7E20
  
  50001B54 3     1 BAMIMA: Bam Buffer 4124    1536 DBMS_LOB 853346312 730DA83C
  
  50001B98 4     1 BAMIMA: Bam Buffer 4128    3456 DBMS_UTILITY 4041615653 730C5FC8
  
  50001BDC 5     1 BAMIMA: Bam Buffer 4132    3760 begin :1 := dbms_lob.getLeng... 2942875191 730CFFCC
  
  50001C20 6     1 state objects    4184    1088 0 00
  
  50001C64 7     1 library cache    4192    488 EXU8VEW  2469165743 730C1C68
  
  50001CA8 8     1 state objects    4196     16 0 730C0B90
  
  50001CEC 9     1 state objects    4216    3608 0 730D0838
  
  3.分析各共享池的使用情况
  SQL> select KSPPINM,KSPPSTVL
  from x$ksppi,
  x$ksppcv
  where x$ksppi.indx = x$ksppcv.indx
  and KSPPINM = '_shared_pool_reserved_min_alloc';
  
  KSPPINM     KSPPSTVL
  -------------------------------  --------
  _shared_pool_reserved_min_alloc  4400  --(门值)
  
  我们看到INDX=5,DBMS_LOB造成换页(就是做exp涉及到lob对象处理造成的换页情况),换出
  最近未使用的内存,但是换出内存并合并碎片后在共享区仍然没有合适区来存放数据,说明共享
  区小和碎片过多,然后根据_shared_pool_reserved_min_alloc的门值来申请保留区,而门值为4400,
  所以不符合申请保留区的条件,造成4031错误。我们前面看到保留区全部为空闲状态,所以我们可以
  减低门值,使更多申请共享内存比4400小的的对象能申请到保留区,而不造成4031错误。
  
  4.解决办法:
  1).增大shared_pool (在不DOWN机的情况下不合适)
  2).打patch  (在不DOWN机的情况下不合适)
  3).减小门值 (在不DOWN机的情况下不合适)
  因为LAST_FAILURE_SIZE<_shared_pool_reserved_min_alloc所以表明没有有效的使用保留区
  SQL> alter system set "_shared_pool_reserved_min_alloc" = 4000;
  alter system set "_shared_pool_reserved_min_alloc"=4000
  *
  ERROR at line 1:
  ORA-02095: specified initialization parameter cannot be modified
  
  -- 9i的使用方法alter system set "_shared_pool_reserved_min_alloc"=4000 scope=spfile;
  
  4).使用alter system flush shared_pool; (不能根本性的解决问题)
  5).使用dbms_shared_pool.keep
  
  5.由于数据库不能DOWN机,所以只能选择3)和4)
  运行dbmspool.sql
  SQL> @/home/oracle/products/8.1.7/rdbms/admin/dbmspool.sql
  找出需要keep到共享内存的对象
  
  SQL> select a.OWNER,
  a.name,
  a.sharable_mem,
  a.kept,
  a.EXECUTIONS ,
  b.address,
  b.hash_value
  from v$db_object_cache a,
  v$sqlarea b
  where a.kept = 'NO' and
  (( a.EXECUTIONS > 1000
  and a.SHARABLE_MEM > 50000)
  or a.EXECUTIONS > 10000)
  and SUBSTR(b.sql_text,1,50) = SUBSTR(a.name,1,50);
  OWNER  NAME            SHARABLE_MEM KEP EXECUTIONS ADDRESS HASH_VALUE
  ------- ----------------------—--- ------------ --- ---------- -------- ----------
  SELECT COUNT(OBJECT_ID)   98292    NO  103207  74814BF8 1893309624
  FROM ALL_OBJECTS
  WHERE OBJECT_NAME = :b1
  AND OWNER = :b2
  
  STANDARD          286632    NO  13501
  DBMS_LOB          98292  NO  103750
  DBMS_LOB        47536    NO  2886542
  DBMS_LOB        11452    NO  2864757
  DBMS_PICKLER        10684    NO  2681194
  DBMS_PICKLER        5224     NO  2663860
  
  SQL> execute dbms_shared_pool.keep('STANDARD');
  SQL> execute dbms_shared_pool.keep('74814BF8,1893309624','C');
  SQL> execute dbms_shared_pool.keep('DBMS_LOB');
  SQL> execute dbms_shared_pool.keep('DBMS_PICKLER');
  SQL> select OWNER, name, sharable_mem,kept,EXECUTIONS from v$db_object_cache where kept = 'YES' ORDER BY sharable_mem;
  SQL> alter system flush shared_pool;
  System altered.
  
  SQL> SELECT POOL,BYTES FROM V$SGASTAT WHERE NAME ='free memory';
  
  POOL       BYTES
  ----------- ----------
  shared pool  7742756
  large pool   614400
  java pool    32768
  
  [oracle@ali-solution oracle]$ sh /home/oracle/admin/dbexp.sh
  
  [oracle@ali-solution oracle]$ grep ORA- /tmp/exp.tmp
  未发现错误,导出数据成功
  
  四、建议:
  由于以上解决的方法是在不能DOWN机的情况下,所以没能动态修改初始化参数,
  但问题的本质是共享区内存过小,需要增加shared pool,使用绑定变量,才能根本
  的解决问题,所以需要在适当的时候留出DOWN机时间,对内存进行合理的配置。

----------------------------------------------------------------------------------------------------------------------------------------------

案例分析:ora-04031与ora-04030错误分析与解决

一:错误总述

1.              ORA-04031
基本上,ORA-04031出现的问题有几个可能性
A. 没有绑定编量造成shared_pool碎片过多,同时shared_pool_size太小.

--这个应该是比较常见的,也是Oracle提的最多的。
--这个通常会建议使用绑定变量,或者简单的加大shared_pool.或者临时解决方法就是alter system flush shared_pool.

B. Large_pool,Java_pool太小造成的

--这个通过错误信息的提示很容易判断(Ora-04031 cannot allocate .. memeory in [large_pool])
--解决方法就是简单的加大 Large_pool or Java_pool

C. 过度的开CURSOR而不关闭。

--这个问题发生的越来越多,特别是在JAVA运行环境中,频频出现。加大Shared_pool或者flush shared_pool往往只能延迟问题出现的时间,而没法避免。
--判断方法:
select count(*) from v$open_cursor ;
select * from v$sysstat
where name = 'opened cursors current';
如果出来的值特大(以万为单位)时,基本就可以确定是这个原因了
--解决这个问题的方法就是检查程序,看是否没有正常的关闭cursor(对于JAVA来说,就是没有关闭Statement)。或者select sql_text from v$open_cursor,看看都是哪些cursor没关闭,再去检查车程序。
--也有的程序使用了保持一定量的cursor一直open,从而避免cursor过多次的开启,来提高性能。对于这种情况,则应该选择适当的shared_pool_size和控制keep_opening的cursor的量。
--也有可能Oracle参数session_cached_cursors太大,解决方法就是把它降低到适当的值

楼主的问题似乎有点象 session_cached_cursors 的问题,但是根据 opened cursors current判断,每个session开的cursor超过1000,已经超过session_cached_cursors,应该检查程序看看。

D. 当然,有时候一些BUG也可能引发ORA-04031,但是在高版本中已经很少出现(>=8174)

2ORA-04030
ORA-04030出现的基本都是过多的使用memory造成的

ORA-04030的问题一般是PGA过度分配造成的(对应的操作是sort/hash_join)。在Oracle9i中pga_aggregate_target指定了所有session总共使用的最大PGA上限,如果该值被设定了则默认的workarea_size_policy=auto, sort_area_size/sort_area_retained_size将被忽略。那么直接减小pga_aggregate_target就能解决一部分ORA-04030问题。

A. 对于32 BIT系统,有SGA 1.7G限制
B. 某些OS系统本身也有一些内存参数限制
--运行 ulimit 看看
C. OS系统本身物理内存+Swap的限制


我们应该检查DB使用的
SGA + PGA 是否超过 上面的限制

SGA 包括 db_cache,shared_pool,large_pool,java_pool
session的PGA包括
sort_area_size/Hash_area_size/*_area_size 或者 pga_aggregate_target
还有执行的CODE以及一些data也会占用空间。

然后再根据情况降低里面的某些值了,比如 db_cache, sort_area_size 等


对于楼主来说,应该是sort_area_size(200M)/Hash_area_size(400M) 太大造成的,降成几十M或者几M 就可以了。

 

二:诊断并解决ORA-04031 错误

当我们在共享池中试图分配大片的连续内存失败的时候,Oracle首先清除池中当前没使用的所有对象,使空闲内存块合并。如果仍然没有足够大单个的大块内存满足请求,就会产生ORA-04031 错误。

当这个错误出现的时候你得到的错误解释信息类似如下:

04031, 00000, "unable to allocate %s bytes of shared memory (/"%s/",/"%s/",/"%s/",/"%s/")"

// *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

// INIT.ORA parameters "shared_pool_reserved_size" and

// "shared_pool_size".

// If the large pool is out of memory, increase the INIT.ORA

// parameter "large_pool_size".

 

1.共享池相关的实例参数

在继续之前,有必要理解下面的实例参数:

 

SHARED_POOL_SIZE
这个参数指定了共享池的大小,单位是字节。可以接受数字值或者数字后面跟上后缀"K" 或 "M" 。"K"代表千字节, "M"代表兆字节。

SHARED_POOL_RESERVED_SIZE
指定了为共享池内存保留的用于大的连续请求的共享池空间。当共享池碎片强制使 Oracle 查找并释放大块未使用的池来满足当前的请求的时候,这个参数和SHARED_POOL_RESERVED_MIN_ALLOC 参数一起可以用来避免性能下降。

这个参数理想的值应该大到足以满足任何对保留列表中内存的请求扫描而无需从共享池中刷新对象。既然操作系统内存可以限制共享池的大小,一般来说,你应该设定这个参数为 SHARED_POOL_SIZE 参数的 10% 大小。

SHARED_POOL_RESERVED_MIN_ALLOC 这个参数的值控制保留内存的分配。如果一个足够尺寸的大块内存在共享池空闲列表中没能找到,内存就从保留列表中分配一块比这个值大的空间。默认的值对于大多数系统来说都足够了。如果你加大这个值,那么Oracle 服务器将允许从这个保留列表中更少的分配并且将从共享池列表中请求更多的内存。这个参数在Oracle 8i 和更高的版本中是隐藏的。提交如下的语句查找这个参数值:

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;

10g 注释:Oracle 10g 的一个新特性叫做 "自动内存管理" 允许DBA保留一个共享内存池来分shared pool,buffer cache, java pool 和large pool。一般来说,当数据库需要分配一个大的对象到共享池中并且不能找到连续的可用空间,将自动使用其他SGA结构的空闲空间来增加共享池的大小 。既然空间分配是Oracle自动管理的,ora-4031出错的可能性将大大降低。自动内存管理在初始化参数SGA_TARGET大于0的时候被激活。当前设定可以通过查询v$sga_dynamic_components 视图获得。请参考10g管理手册以得到更多内容 。

2.诊断ORA-04031 错误

注:大多数的常见的 ORA-4031 的产生都和 SHARED POOL SIZE 有关,这篇文章中的诊断步骤大多都是关于共享池的。 对于其它方面如Large_pool或是Java_pool,内存分配算法都是相似的,一般来说都是因为结构不够大造成。

ORA-04031 可能是因为 SHARED POOL 不够大,或是因为碎片问题导致数据库不能找到足够大的内存块。

ORA-04031 错误通常是因为库高速缓冲中或共享池保留空间中的碎片。 在加大共享池大小的时 候考虑调整应用,使用共享的SQL 并且调整如下的参数:

SHARED_POOL_SIZE,

SHARED_POOL_RESERVED_SIZE,

SHARED_POOL_RESERVED_MIN_ALLOC.

首先判定是否ORA-04031 错误是由共享池保留空间中的库高速缓冲的碎片产生的。提交下的查询:

SELECT free_space, avg_free_size,used_space, avg_used_size, request_failures,

       last_failure_size

  FROM v$shared_pool_reserved;

如果:

REQUEST_FAILURES > 0 并且 LAST_FAILURE_SIZE > SHARED_POOL_RESERVED_MIN_ALLOC

那么ORA-04031 错误就是因为共享池保留空间缺少连续空间所致。要解决这个问题,可以考虑加大SHARED_POOL_RESERVED_MIN_ALLOC 来降低缓冲进共 享池保留空间的对象数目,并增大 SHARED_POOL_RESERVED_SIZE 和 SHARED_POOL_SIZE 来加大共享池保留空间的可用内存。

如果:

REQUEST_FAILURES > 0 并且 LAST_FAILURE_SIZE < SHARED_POOL_RESERVED_MIN_ALLOC

或者

REQUEST_FAILURES 等于0 并且 LAST_FAILURE_SIZE < SHARED_POOL_RESERVED_MIN_ALLOC

那么是因为在库高速缓冲缺少连续空间导致ORA-04031 错误。

第一步应该考虑降低SHARED_POOL_RESERVED_MIN_ALLOC 以放入更多的对象到共享池保留空间中并且加大SHARED_POOL_SIZE。

3.解决ORA-04031 错误

ORACLE BUG

Oracle推荐对你的系统打上最新的PatchSet。大多数的ORA-04031错误都和BUG 相关,可以通过使用这些补丁来避免。

下面表中总结和和这个错误相关的最常见的BUG、可能的环境和修补这个问题的补丁。

BUG

描述

Workaround

Fixed

<Bug:1397603>

ORA-4031/SGA memory leak of PERMANENT memory occurs for buffer handles

_db_handles_cached = 0

901/ 8172

<Bug:1640583>

ORA-4031 due to leak / cache buffer chain contention from AND-EQUAL access

Not available

8171/901

<Bug:1318267>

INSERT AS SELECT statements may
not be shared when they should be
if TIMED_STATISTICS. It can lead to ORA-4031

_SQLEXEC_PROGRESSION_COST=0

8171/8200

<Bug:1193003>

Cursors may not be shared in 8.1
when they should be

Not available

8162/8170/ 901

<Bug:2104071>

ORA-4031/excessive "miscellaneous" shared pool usage possible. (many PINS)

None-> This is known to affect the XML parser.

8174, 9013, 9201

<Note:263791.1>

Several number of BUGs related to ORA-4031 erros were fixed in the 9.2.0.5 patchset

Not available

9205

 

  • 编译Java代码时出现的ORA-4031

在你编译Java代码的时候如果内存溢出,你会看到错误:

A SQL exception occurred while compiling: :

ORA-04031: unable to allocate bytes of shared memory ("shared pool","unknown object","joxlod: init h", "JOX: ioc_allocate_pal")

解决办法是关闭数据库然后把参数 JAVA_POOL_SIZE 设定为一个较大的值。这里错误信息中提到的 "shared pool" 其实共享全局区(SGA)溢出的误导,并不表示你需要增加SHARED_POOL_SIZE,相反,你必须加大 JAVA_POOL_SIZE 参数的值,然后重启动系统,再试一下。参考: <Bug:2736601> 。

  • 小的共享池尺寸

很多情况下,共享池过小能够导致ORA-04031错误。下面信息有助于你调整共享池大小:

库高速缓冲命中率

命中率有助于你衡量共享池的使用,有多少语句需要被解析而不是重用。下面的SQL语句有助于你计算库高速缓冲的命中率:

SELECT SUM(PINS) "EXECUTIONS",

SUM(RELOADS) "CACHE MISSES WHILE EXECUTING"         

FROM V$LIBRARYCACHE;

如果丢失超过1%,那么尝试通过加大共享池的大小来减少库高速缓冲丢失。

共享池大小计算

要计算最适合你工作负载的共享池大小,请参考:

<Note:1012046.6>: HOW TO CALCULATE YOUR SHARED POOL SIZE.

  • 共享池碎片

每一次,需要被执行的SQL 或者PL/SQL 语句的解析形式载入共享池中都需要一块特定的连续的空间。数据库要扫描的第一个资源就是共享池中的空闲可用内存。一旦空闲内存耗尽,数据库要查找一块已经分配但还没使用的内存准备重用。如果这样的确切尺寸的大块内存不可用,就继续按照如下标准寻找:

IXDBA.NET社区论坛

  • 大块(chunk)大小比请求的大小大
  • 空间是连续的
  • 大块内存是可用的(而不是正在使用的)

这样大块的内存被分开,剩余的添加到相应的空闲空间列表中。当数据库以这种方式操作一段时间之后,共享池结构就会出现碎片。

当共享池存在碎片的问题,分配一片空闲的空间就会花费更多的时间,数据库性能也会下降(整个操作的过程中,"chunk allocation"被一个叫做"shared pool latch" 的闩所控制) 或者是出现 ORA-04031 错误errors (在数据库不能找到一个连续的空闲内存块的时候)。

参考 <Note:61623.1>: 可以得到关于共享池碎片的详细讨论。

如果SHARED_POOL_SIZE 足够大,大多数的 ORA-04031 错误都是由共享池中的动态SQL 碎片导致的。可能的原因如下:

  • 非共享的SQL
  • 生成不必要的解析调用 (软解析)
  • 没有使用绑定变量

要减少碎片的产生你需要确定是前面描叙的几种可能的因素。可以采取如下的一些方法,当然不只局限于这几种: 应用调整、数据库调整或者实例参数调整。

请参考 <Note:62143.1>,描述了所有的这些细节内容。这个注释还包括了共享池如何工作的细节。

下面的视图有助于你标明共享池中非共享的SQL/PLSQL:

  • V$SQLAREA 视图

这个视图保存了在数据库中执行的SQL 语句和PL/SQL 块的信息。下面的SQL 语句可以显示给你带有literal 的语句或者是带有绑定变量的语句:

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 (*) > 30

ORDER BY 2;

注: Having 后的数值 "30" 可以根据需要调整以得到更为详细的信息。

  • X$KSMLRU 视图

这个固定表x$ksmlru 跟踪共享池中导致其它对象换出(age out)的应用。这个固定表可以用来标记是什么导致了大的应用。

如果很多对象在共享池中都被阶段性的刷新可能导致响应时间问题并且有可能在对象重载入共享池中的时候导致库高速缓冲闩竞争问题。

关于这个x$ksmlru 表的一个不寻常的地方就是如果有人从表中选取内容这个表的内容就会被擦除。这样这个固定表只存储曾经发生的最大的分配。这个值在选择后被重新设定这样接下来的大的分配可以被标记,即使它们不如先前的分配过的大。因为这样的重置,在查询提交后的结果不可以再次得到,从表中的输出的结果应该小心的保存。监视这个固定表运行如下操作:

SELECT * FROM X$KSMLRU WHERE ksmlrsiz > 0;

这个表只可以用SYS用户登录进行查询。

  • X$KSMSP 视图 (类似堆Heapdump信息)

使用这个视图能找出当前分配的空闲空间,有助于理解共享池碎片的程度。如我们在前面的描述,查找为游标分配的足够的大块内存的第一个地方是空闲列表( free list)。 下面的语句显示了空闲列表中的大块内存:

SELECT   '0 (<140)' bucket, ksmchcls, 10 * TRUNC (ksmchsiz / 10) "From",

         COUNT (*) "Count", MAX (ksmchsiz) "Biggest",

         TRUNC (AVG (ksmchsiz)) "AvgSize", TRUNC (SUM (ksmchsiz)) "Total"

    FROM x$ksmsp

   WHERE ksmchsiz < 140 AND ksmchcls = 'free'

GROUP BY ksmchcls, 10 * TRUNC (ksmchsiz / 10)

UNION ALL

SELECT   '1 (140-267)' bucket, ksmchcls, 20 * TRUNC (ksmchsiz / 20),

         COUNT (*), MAX (ksmchsiz), TRUNC (AVG (ksmchsiz)) "AvgSize",

         TRUNC (SUM (ksmchsiz)) "Total"

    FROM x$ksmsp

   WHERE ksmchsiz BETWEEN 140 AND 267 AND ksmchcls = 'free'

GROUP BY ksmchcls, 20 * TRUNC (ksmchsiz / 20)

UNION ALL

SELECT   '2 (268-523)' bucket, ksmchcls, 50 * TRUNC (ksmchsiz / 50),

         COUNT (*), MAX (ksmchsiz), TRUNC (AVG (ksmchsiz)) "AvgSize",

         TRUNC (SUM (ksmchsiz)) "Total"

    FROM x$ksmsp

   WHERE ksmchsiz BETWEEN 268 AND 523 AND ksmchcls = 'free'

GROUP BY ksmchcls, 50 * TRUNC (ksmchsiz / 50)

UNION ALL

SELECT   '3-5 (524-4107)' bucket, ksmchcls, 500 * TRUNC (ksmchsiz / 500),

         COUNT (*), MAX (ksmchsiz), TRUNC (AVG (ksmchsiz)) "AvgSize",

         TRUNC (SUM (ksmchsiz)) "Total"

    FROM x$ksmsp

   WHERE ksmchsiz BETWEEN 524 AND 4107 AND ksmchcls = 'free'

GROUP BY ksmchcls, 500 * TRUNC (ksmchsiz / 500)

UNION ALL

SELECT   '6+ (4108+)' bucket, ksmchcls, 1000 * TRUNC (ksmchsiz / 1000),

         COUNT (*), MAX (ksmchsiz), TRUNC (AVG (ksmchsiz)) "AvgSize",

         TRUNC (SUM (ksmchsiz)) "Total"

    FROM x$ksmsp

   WHERE ksmchsiz >= 4108 AND ksmchcls = 'free'

GROUP BY ksmchcls, 1000 * TRUNC (ksmchsiz / 1000);

4. ORA-04031 错误与 Large Pool

大池是个可选的内存区,为以下的操作提供大内存分配:

  • MTS会话内存和 Oracle XA 接口
  • Oracle 备份与恢复操作和I/O服务器进程用的内存(缓冲)
  • 并行执行消息缓冲

大池没有LRU列表。这和共享池中的保留空间不同,保留空间和共享池中其他分配的内存使用同样的LRU列表。大块内存从不会换出大池中,内存必须是显式的被每个会话分配并释放。一个请求如果没有足够的内存,就会产生类似这样的一个ORA-4031错误:

ORA-04031: unable to allocate XXXX bytes of shared memory

("large pool","unknown object","session heap","frame")

这个错误发生时候可以检查几件事情:

  • 1- 使用如下语句检查 V$SGASTAT ,得知使用和空闲的内存:
  • SELECT pool,name,bytes FROM v$sgastat where pool = 'large pool';
  • 2- 你还可以采用 heapdump level 32 dump 大池的堆并检查空闲的大块内存的大小

从大池分配的内存如果是LARGE_POOL_MIN_ALLOC 子节的整块数有助于避免碎片。任何请求分配小于LARGE_POOL_MIN_ALLOC 大块尺寸都将分配LARGE_POOL_MIN_ALLOC的大小。一般来说,你会看到使用大池的时候相对共享池来说要用到更多的内存。通常要解决大池中的ORA-4031错误必须增加 LARGE_POOL_SIZE 的大小。

 

5. ORA-04031 和共享池刷新


有一些技巧会提高游标的共享能力,从而共享池碎片和ORA-4031都会减少。最佳途径是调整应用使用绑定变量。另外在应用不能调整的时候考虑使用CURSOR_SHARING参数和FORCE不同的值来做到 (要注意那会导致执行计划改变,所以建议先对应用进行测试)。当上述技巧都不可以用的时候,并且碎片问题在系统中比较严重,刷新共享持可能有助于减轻碎片问题。但是,必须加以如下考虑:

  • 刷新将导致所有没被使用的游标从共享池删除。这样,在共享池刷新之后,大多数SQL和PL/SQL游标必须被硬解析。这将提高CPU的使用,也会加大Latch的活动。
  • 当应用程序没有使用绑定变量并被许多用户进行类似的操作的时候(如在OLTP系统中) ,刷新之后很快还会出现碎片问题。所以共享池对设计糟糕的应用程序来说不是解决办法。
  • 对一个大的共享池刷新可能会导致系统挂起,尤其是实例繁忙的时候,推荐在非高峰的时候刷新

6. ORA-04031错误的高级分析

如果前述的这些技术内容都不能解决ORA-04031 错误,可能需要额外的跟踪信息来得到问题发生的共享池的快照。

调整init.ora参数添加如下的事件得到该问题的跟踪信息:

event = "4031 trace name errorstack level 3"

event = "4031 trace name HEAPDUMP level 3"

如果问题可重现,该事件可设定在会话层,在执行问题语句之前使用如下的语句:

SQL> alter session set events '4031 trace name errorstack level 3';

SQL> alter session set events '4031 trace name HEAPDUMP level 3';

把这个跟踪文件发给Oracle支持人员进行排错。

重要标注: Oracle 9.2.0.5 和Oracle 10g 版本中,每次在发生ORA-4031 错误的时候会自动创建一个跟踪文件,可以在user_dump_dest 目录中找到。如果你的系统是上述的版本,你不需要再进行前面描述中的步骤。

原文地址:https://www.cnblogs.com/lteal/p/3030109.html