转自:http://www.hellodba.com/reader.php?ID=110&lang=CN
3. 内存错误处理
3.1. 分析、定位ORA-4030
3.1.1. 4030错误产生的原因
3.1.2. 4030错误分析
3.1.2.1. 操作系统是否由足够的内存
- Physical
Memory Usage (pages): Total Free In Use Modified Main Memory (256.00Mb) 32768 24849 7500 419 -
..... - Paging
File Usage (blocks): Free Reservable Total -
DISK$BOBBIEAXPSYS:[SYS0.SYSEXE]SWAPFILE.SYS 30720 30720 39936 DISK$BOBBIEAXPSYS:[SYS0.SYSEXE]PAGEFILE.SYS 226160 201088 249984 DISK$BOBBIE_USER3:[SYS0.PAGEFILE]PAGEFILE.SYS 462224 405296 499968
- >
swapinfo -mt -
Mb Mb Mb PCT START/ Mb - TYPE
AVAIL USED FREE USED LIMIT RESERVE PRI NAME - dev
4096 0 4096 0% 0 - 1 /dev/vg00/lvol2 - dev
8000 0 8000 0% 0 - 1 /dev/vg00/swap2 - reserve
- 12026 -12026 - memory
20468 13387 7081 65% - total
32564 25413 7151 78% - 0 - -
- >
maxmem - Memory
starts at: 6917529027641212928 (6000000000020000) - Memory
ends at: 6917529031936049152 (6000000100000000) - Memory
available: 4294836224 (fffe0000)
3.1.2.2. 是否受到系统限制
- >
ulimit -a - time(seconds)
unlimited - file(blocks)
unlimited - data(kbytes)
1048576 - stack(kbytes)
131072 - memory(kbytes)
unlimited - coredump(blocks)
4194303
3.1.2.3. 哪个Oracle进程请求了过多的内存
select sid,name,valuefrom v$statname n,v$sesstat swhere n.STATISTIC# = s.STATISTIC# and name like '%ga %'order by 3 asc;
3.1.2.4. 收集进程正在进行的操作
- select
sql_text - from
v$sqlarea a, v$session s - where
a.address = s.sql_address and s.sid = ;
另外,可以做一个heapdump,将结果发给Oracle进行分析,
- SQL>
oradebug unlimitSQL> oradebug setorapid (通过v$process查到的pid, 用setospid来设置OS中的PID【或者v$process中的spid】)SQL> oradebug dump heapdump 7 (1-PGA; 2-Shared Pool; 4-UGA; 8-CGA; 16-top CGA; 32-large pool) - SQL>
alter session set events '4030 trace name heapdump level 25';
3.1.3. 解决4030错误的建议
3.2. 分析、定位ORA-4031
3.2.1. 4031错误产生的原因
3.2.2. 4031错误分析
3.2.2.1. 对shared pool的分析
3.2.2.2. 对large pool的分析
3.2.3. 解决4031错误
3.2.3.1. bug导致的错误
BUG | 说明 | 修正版本 |
Bug 1397603 | ORA-4031 | 8172, 901 |
Bug 1640583 | ORA-4031 due to leak / | 8171, 901 |
| 如果设置了TIMED_STATISTICS可能导致INSERT AS SELECT无法被共享。 | 8171, |
| Oracle 8.1中,某些游标不共享。 | 8162, 8170, 901 |
Bug 2104071 | ORA-4031 | 8174, 9013, 9201 |
Note 263791.1 | 许多与4031相关的错误在9205补丁集中修正。 | 9205 |
3.2.3.2. Shared pool太小
大多数4031错误都是由shared pool不足导致的。可以从以下几个方面来考虑是否调整shared pool大小:
·
通过以下语句可以查出系统的library cache命中率:
SELECT SUM(PINS) "EXECUTIONS", SUM(RELOADS) "CACHE MISSES WHILE EXECUTING", 1 - SUM(RELOADS)/SUM(PINS)FROM V$LIBRARYCACHE;
如果命中率小于99%,就可以考虑增加shared pool以提高library cache的命中率。
·
以下语句可以查看shared pool的使用情况
select sum(bytes) from v$sgastat
where pool='shared pool'
and name != 'free memory';
专用服务模式下,以下语句查看cache在内存中的对象的大小,
select sum(sharable_mem) from v$db_object_cache;
专用服务模式下,以下语句查看SQL占用的内存大小,
select sum(sharable_mem) from v$sqlarea;
Oracle需要为保存每个打开的游标分配大概250字节的内存,以下语句可以计算这部分内存的占用情况,
select sum(250 * users_opening) from v$sqlarea;
此外,在我们文章的前面部分有多处提到了如何分析shared pool是否过大或过小,这里就不在赘述。
3.2.3.3. Shared pool碎片
- 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;
- SELECT
* FROM X$KSMLRU WHERE ksmlrsiz > 0;
- select
'0 (<140)' BUCKET, KSMCHCLS, KSMCHIDX, 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, KSMCHIDX, 10*trunc(KSMCHSIZ/10) UNION ALL select '1 (140-267)' BUCKET, KSMCHCLS, KSMCHIDX,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, KSMCHIDX, 20*trunc(KSMCHSIZ/20) UNION ALL select '2 (268-523)' BUCKET, KSMCHCLS, KSMCHIDX, 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, KSMCHIDX, 50*trunc(KSMCHSIZ/50) UNION ALL select '3-5 (524-4107)' BUCKET, KSMCHCLS, KSMCHIDX, 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, KSMCHIDX, 500*trunc(KSMCHSIZ/500) UNION ALL select '6+ (4108+)' BUCKET, KSMCHCLS, KSMCHIDX, 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, KSMCHIDX, 1000*trunc(KSMCHSIZ/1000);
3.2.3.4. 编译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")
这里提示时shared pool不足,其实是错误,实际应该是java pool不足导致的。解决方法将JAVA_POOL_SIZE加大,然后重启实例。
3.2.3.5. Large pool导致的错误
- SELECT
pool,name,bytes FROM v$sgastat where pool = 'large pool';
3.2.4. SGA内存自动管理
3.2.5. FLUSH SHARED POOL
- alter
system flush shared_pool;
3.2.6. TRACE 4031错误
- SQL>
alter system set events '4031 trace name errorstack level 3'; SQL> alter system set events '4031 trace name HEAPDUMP level 3';