案例分享:ORA-04030 out of process memory
[TOC]
一、环境介绍
架构 | 版本 | SGA大小 | PGA大小 | OS内存 |
---|---|---|---|---|
单机 | 11.2.0.3 | 30G | 6G | 78G |
二、问题描述
- 客户反馈应用执行程序抛出ORA-4030错误。
- 检查aler 日志,发现如下大量错误:
Thu Mar 13 15:49:48 2025 Exception [type: SIGSEGV, Address not mapped to object] [ADDR:0x7FFDC2F9CBD8] [PC:0x77FB951, kgdsdsts_extra()+81] [flags: 0x0, count: 1] Errors in file /u01/app/oracle/diag/rdbms/xxxx/xxxx/trace/xxxx_ora_26404.trc: ORA-07445: exception encountered: core dump [kgdsdsts_extra()+81] [SIGSEGV] [ADDR:0x7FFDC2F9CBD8] [PC:0x77FB951] [Address not mapped to object] [] ORA-04030: out of process memory when trying to allocate 16408 bytes (QERHJ hash-joi,QERHJ Bit vector) ... ... Errors in file /u01/app/oracle/diag/rdbms/xxxx/xxxx/trace/xxxx_cjq0_10312.trc: Errors in file /u01/app/oracle/diag/rdbms/xxxx/xxxx/incident/incdir_3161576/xxxx_ora_26193_i3161576.trc: ORA-04030: out of process memory when trying to allocate 1052696 bytes (pga heap,log read buffer) ... ... Errors in file /u01/app/oracle/diag/rdbms/xxxx/xxxx/trace/xxxx_m000_25904.trc: ORA-04030: out of process memory when trying to allocate 368 bytes (session heap,kocca) ... ... Errors in file /u01/app/oracle/diag/rdbms/xxxx/xxxx/trace/xxxx_j000_22866.trc: ORA-07445: ³öϖҬ³£´펳: ºːėª´¢ [kgdsdsts_extra()+81] [SIGSEGV] [ADDR:0x7FFD8B8E6138] [PC:0x77FB951] [Address not mapped to object] [] ORA-04030: Ԛ³¢ʔ·օ䠸168 ז½ڠ(callheap,kcbtmal allocation) ʱ½ø³̄ڴ治ף
复制
三、故障分析
初步检查:
1)从报错信息来看,主要是抛出 ORA-04030: out of process memory ,内存不足的错误信息,同时对应的错误代码有session heap,kocca、pga heap,log read buffer等等
2)检查操作系统资源使用情况:存在swap占用。
分析到这里,我们怀疑是操作系统层面,内存不够导致的,初步解决方案:增量物理内存,同时顺便调整SGA大小。
四、解决办法
由于是虚拟机,增加物理内存比较方便,直接从78G 调整到128G,同时调整SGA大小,从30G调整到48G。
1)调整内存大小
🎈申请停机时间,开始调整:
-
1)系统层面,调整参数
kernel.shmmax
kernel.shmall -
2)数据库层面,调整SGA值
😂修改操作都很顺利,数据库正常启动后,通知应用测试,结果应用程序一跑,立马抛出了ORA-4030错误,检查系统负载,系统负载较轻,内存空闲较多,什么情况,大大的无语!
深度检查:
1)赶紧查mos、查百度、大部分文档都是说PGA单进程超过了4G限制,建议调整max_map_count值。
- 参考Doc ID 1929790.1**、**Doc ID 1325100.1
目的:是为了调整单进程PGA最大可用内存从默认的4G调整到为16G。
-- 默认是65530
$ cat /proc/sys/vm/max_map_count
65530
复制
于是,赶紧在维护窗口内,调整了max_map_count值,重启服务器、数据库。结果,仍然报错。
2)仔细查看trace文件:pga只用了78M内存,所以并不是上面的问题导致的。
3)停机时间有限,我们先恢复了SGA大小,重新改成30G,重启数据库后,应用使用正常。
🤣加了内存,SGA怎么加不上去了呢?开个case问一下support,最终回复如下:
2)调整系统参数
a. 理解overcommit
在Unix中,当一个用户进程使用malloc()函数申请内存时,假如返回值是NULL,则这个进程知道当前没有可用内存空间,就会做相应的处理工作。许多进程会打印错误信息并退出。
Linux使用另外一种处理方式,它对大部分申请内存的请求都回复yes
,以便能跑更多更大的程序。因为申请内存后,并不会马上使用内存。这种技术叫做Overcommit。也就是说malloc的时候不真的分配内存,而是在memset的时候分配。
当内存不足时,会发生OOM killer(OOM=out-of-memory)。它会选择杀死一些进程(用户态进程,不是内核线程),以便释放内存。
b. overcommit三种策略
-
0 :默认设置。内核执行启发式内存过量使用处理,方法是估算可用内存量,并拒绝明显无效的请求。遗憾的是因为内存是使用启发式而非准确算法计算进行部署,这个设置有时可能会造成系统中的可用内存超载。
-
1 :允许overcommit。内核执行无内存过量使用处理。使用这个设置会增大内存超载的可能性,但也可以增强大量使用内存任务的性能。
-
2 :不允许overcommit,即超过CommitLimit的数值就会申请内存失败。CommitLimit只在overcommit_memory=2时有效。
换言之,内存拒绝等于或者大于总可用 swap 大小以及 overcommit_ratio指定的物理 RAM比例的内存请求。overcommit_ratio默认是50,即 CommitLimit = swap + mem * 50 / 100
检查当前环境信息:
$ cat /proc/sys/vm/overcommit_memory
$ cat /proc/sys/vm/overcommit_ratio
$ grep -i commit /proc/meminfo
复制
👉️ 最终解决办法:删除 vm.overcommit_memory 配置,重启服务器、数据库。
再次调整SGA从30G到48G,应用使用正常。至此,问题得到顺利解决。