04031导致数据库实例宕机

问题描述
某用户Oracle数据库数据库突然宕机,查看日志发现宕机前大量出现如下错误:

Errors in file /u01/oracle/admin/orcl/bdump/orcl2_smon_14347.trc: ORA-00604: Message 604 not found; No message file for product=RDBMS, facility=ORA; arguments: [2] ORA-04031: Message 4031 not found; No message file for product=RDBMS, facility=ORA; arguments: [32] [shared pool] [select /*+ rule */ bucket_cn...] [sql area] [tmp] Thu Nov 12 15:43:54 2015 Errors in file /u01/oracle/admin/orcl/bdump/orcl2_smon_14347.trc: ORA-00604: Message 604 not found; No message file for product=RDBMS, facility=ORA; arguments: [2] ORA-04031: Message 4031 not found; No message file for product=RDBMS, facility=ORA; arguments: [32] [shared pool] [select /*+ rule */ bucket_cn...] [sql area] [tmp] Thu Nov 12 15:43:55 2015 WARNING: inbound connection timed out (ORA-3136) Thu Nov 12 15:43:56 2015 WARNING: inbound connection timed out (ORA-3136) Thu Nov 12 15:43:58 2015 WARNING: inbound connection timed out (ORA-3136) Thu Nov 12 15:43:59 2015 Errors in file /u01/oracle/admin/orcl/bdump/orcl2_smon_14347.trc: ORA-00604: Message 604 not found; No message file for product=RDBMS, facility=ORA; arguments: [2] ORA-04031: Message 4031 not found; No message file for product=RDBMS, facility=ORA; arguments: [32] [shared pool] [select /*+ rule */ bucket_cn...] [sql area] [tmp] Thu Nov 12 15:44:00 2015 Errors in file /u01/oracle/admin/orcl/bdump/orcl2_smon_14347.trc: ORA-00604: Message 604 not found; No message file for product=RDBMS, facility=ORA; arguments: [2] ORA-04031: Message 4031 not found; No message file for product=RDBMS, facility=ORA; arguments: [32] [shared pool] [select /*+ rule */ bucket_cn...] [sql area] [tmp] Thu Nov 12 15:44:00 2015 WARNING: inbound connection timed out (ORA-3136) Thu Nov 12 15:44:01 2015 Errors in file /u01/oracle/admin/orcl/bdump/orcl2_smon_14347.trc: ORA-00604: Message 604 not found; No message file for product=RDBMS, facility=ORA; arguments: [2] ORA-04031: Message 4031 not found; No message file for product=RDBMS, facility=ORA; arguments: [32] [shared pool] [select /*+ rule */ bucket_cn...] [sql area] [tmp] Thu Nov 12 15:44:02 2015 WARNING: inbound connection timed out (ORA-3136) Thu Nov 12 15:44:02 2015 Errors in file /u01/oracle/admin/orcl/bdump/orcl2_smon_14347.trc:

这里ORA-04031很清楚地表示出来,是在向shared pool申请内存时失败。
shared pool内存申请(分配)失败,通常有如下的几种可能:

shared pool过小,比如在SGA Manual Management方式下,shared pool设置过小。比如一套数千连接的大系统,shared pool只设置了几百M。这种情况下,要解决问题很解单,增加shared pool的大小即可。

应用没有使用绑定变量,硬解析非常多,导致shared pool内存碎片严重,分配大块内存时不能获得连续的内存空间。硬解析多的一个变种是虽然使用了绑定变量,但是由于某种原因,Cursor不能共享,导致 Child Cursor非常多。实际上,如果shared pool较大(比如数GB大小),这种问题还是很少出现的,并且出现也通常出现在申请大块内存时。这种情况如果使用alter system flush shared_pool可以暂时缓解问题。但是这条命令又通常不适用于shared pool较大而且比较繁忙的系统。使用绑定变量

Cache的cursor很多,同时cursor_space_for_time这一参数设置为TRUE,可能会使shared pool碎片化严重,导致不能分配到大块的连续内存。

Oracle的BUG导致内存泄露,比如在一些版本中查询v$segment_statistics这样的视图导致内存泄露,使shared pool内存耗光。同样的情形还有类似于“obj stat memory”,”gcs resources”,”ges resources”等。通常这类内存为perm类型(permanet),这类内存通常是在分配时就确定了固定的用途,不能用于其他用途,因此极容易产生碎片。

Oracle从9i开始,根据shared pool的大小将shared pool分为多个子池(subpool),每个子池有独立的free list,同时在分配时单独管理(有其独立 的shared pool latch)。Oracle的BUG或者说是内存分配策略缺陷导致某一类shared pool的内存分配只在一个子池(subpool)中,即多个子池的使用极不均衡,导致向那个使用得最多的子池申请内存时失败。报错信息中的”sga heap(3,0)”即指明是在第3个子池申请内存时失败。本文案例中的ORA-04031错误其产生的原因可以归结为Oracle对shared pool的分配/使用策略问题。

操作系统内存不足,这只会出现在shared pool的使用还没有达到最大值时才会出现,并且在操作系统都有swap的情况下,只有部分操作系统才可能有这种情况,比如在HP-UX下,reserved 内存过多导致swap满。

其他原因,多数是因为BUG。

内容版权声明:除非注明,否则皆为本站原创文章。

转载注明出处:https://www.heiqu.com/75c1b1848d6a3f8329e5f192d0aa27db.html