Apr 18 08:35:56 primer kernel: Out of memory: kill process 3718 (oracle) score 94986 or a child
Apr 18 08:35:56 primer kernel: Killed process 3718 (oracle)
这是linux的一种保护机制,用于避免在内存不足的时候不至于出现严重问题,把一些无关的进程优先杀掉,即在内存严重不足时,系统为了继续运转,内核会挑选一个进程,将其杀掉,以释放内存,缓解内存不足情况,不过这种保护是有限的,不能完全的保护进程的运行。
该问题是low memory耗尽,因为内核使用low memory来跟踪所有的内存分配。当low memory耗尽,不管high memory剩多少,oom-killer都会杀死进程,以保持系统的正常运行。
当low memory耗尽,不管high memory剩多少,oom-killer都会杀死进程,以保持系统的正常运行。
在32位CPU下寻址范围是有限的,Linux内核定义了下面三个区域:
# DMA: 0x00000000 - 0x00999999 (0 - 16 MB) # LowMem: 0x01000000 - 0x037999999 (16 - 896 MB) - size: 880MB # HighMem: 0x038000000 - <硬件特定>
linux omm 机制
同时这里还涉及到内核当内存耗尽时的一种策略,/proc/sys/vm/overcommit_memory可用于配置这种策略:
overcommit_memory == 2,物理内存使用完后,打开任意一个程序均显示内存不足;
overcommit_memory == 1,会从buffer中释放较多物理内存,oom-kill也会继续起作用;
overcommit_memory ==0,系统默认设置,释放较少物理内存,使得oom-kill机制运作比较明显。
也就是说,如果overcommit_memory==2时,内存耗尽时,oom-kill是不会起作用的,系统不会再打开其他程序了,只有等待正在运行的进程释放内存。
解决办法
修改 omm 策略
添加一下行到/etc/sysctl
#add for omm
vm.overcommit_memory = 1
Linux下每个进程都有个OOM权重,在/proc/<pid>/oom_adj里面,取值是-17到+15,取值越高,越容易被干掉。
我们可以只针对单一进程处理,把某个进程保护起来,此时,我们可以使用如下命令:
echo -17 > /proc/[pid]/oom_adj
/proc/[pid]/oom_adj中oom_adj的取值范围是-17~15,当该值为-17时,系统将不会杀死指定pid的进程,而-16~15则会使得进程的/proc/[pid]/oom_adj值呈指数(K*2^n)形式递增,即它们被杀掉的可能性呈指数递增。针对init(进程号为1)这个进程,无论该值设为多少都不会被杀。
另外:Linux在计算进程的内存消耗的时候,会将子进程所耗内存的一半同时算到父进程中。这样,那些子进程比较多的进程就要小心了,比如oracle的父进程。