同事在 Linux 服务器上遇到点小问题,我也上去折腾半天。这还是第一次注意到 Linux 这个多年来就存在的特性:OOM Killer 。说白了 OOM Killer 就是一层保护机制,用于避免 Linux 在内存不足的时候不至于出太严重的问题,把无关紧要的进程杀掉,有些壮士断腕的意思。
先要学习点老知识,在 32 位CPU 架构下寻址是有限制的。Linux 内核定义了三个区域:
# DMA: 0x00000000 - 0x00999999 (0 - 16 MB)
# LowMem: 0x01000000 - 0x037999999 (16 - 896 MB) - size: 880MB
# HighMem: 0x038000000 - <硬件特定>
LowMem 区 (也叫 NORMAL ZONE ) 一共 880 MB,而且不能改变(除非用 hugemem 内核)。对于高负载的系统,就可能因为 LowMem 利用不好而引发 OOM Killer 。一个可能原因是 LowFree 太少了,另外一个原因是 LowMem 里都是碎片,请求不到连续的内存区域【根据我遇到的一个案例,一个猜想是 有些应用一次性请求比较大的内存,恰恰又是 880M 之内的,空闲的(LowFree)不够大,就会触发 OOM Killer 出来干活】。检查当前 LowFree 的值:
# cat /proc/meminfo |grep LowFree
检查LowMem内存碎片:
# cat /proc/buddyinfo
上面这条命令要在 2.6 Kernel 环境下有效。据说使用 SysRq 的方式更好,不过 Hang 的时候再用吧。参见 Metalink Note:228203.1 。
根据一些文档描述,OOM Killer 在 2.4 与 2.6 上表现是不一样的。2.4 的版本中是把新进来(新申请内存)的进程杀掉。而 2.6 上是杀掉占用内存最厉害的进程(这是很危险的,很容易导致系统应用瘫痪)。
对于 RHEL 4 ,新增了一个参数: vm.lower_zone_protection 。这个参数默认的单位为 MB,默认 0 的时候,LowMem 为 16MB。建议设置 vm.lower_zone_protection = 200 甚至更大以避免 LowMem 区域的碎片,是绝对能解决这个问题的(这参数就是解决这个问题出来的)。
而对于 RHEL 3 (Kernel 2.4) 似乎没什么好办法,一个是用 Hugemem 内核(天知道会不会引入新的毛病),一个是升级到 2.4.21-47 并且使用新的核心参数 vm.vm-defragment 控制碎片的数量。再就是使用 RHEL 4 (Kernel 2.6),这又绕回去了。说白了,如果遇到 OOM Killer ,基本上是低版本 Kernel 设计上有点缺陷。
其它,如果去查询 RedHat 的 Bug 库,会发现不少 Kernel 版本也有 Bug 的。尤其在使用 NFS 的场景。
Tip: OOM Killer 的关闭与激活方式:
# echo "0" > /proc/sys/vm/oom-kill
# echo "1" > /proc/sys/vm/oom-kill
更多参考信息:
- 1) OOM killer “Out of Memory: Killed process” SOLUTIONS / SUMMARY【对我遇到的案例没鸟用】
- 2) Metalink Notes : Linux Kernel Lowmem Pressure Issues and Kernel Structures
- 3) Respite from the OOM killer
–EOF–
头疼欲裂,零散记录点东西,备查。
我之前是用过升级到hugemem的内核版本解决这个问题的,,系统之后稳定的运行了2年没有出问题吧..
你们倒是也可以试试..
我升级之后使用的版本为..
2.4.21-32.0.1.ELhugemem #1
我们用的32位系统一直存在这个问题,880M的限制是为4G以下内存设计的,如果物理内存大于4G并打开PAE的话,LowMem很容易爆掉。如果内核保护得好没有爆掉的话,也会有一大片物理内存利用不上。
升级到64位系统就解决了这个问题,因为64位系统下所有的内存都是LowMem。
@forcey
我这边最后对链接进来的进程数做了控制。“避免”了问题的再次出现。长期来看,还是找个机会升级到 64 位机器上。
当年,上学时,我们老师就在给我们讲,做我们这一行的(IT),身体状况就没一个完好的,都是处于亚健康状态,,,,,看来又多了一个,呵呵!~~
哥们可要注意身体哟!!
光说这个实在太少. OOM 问题和大 tmpfs(用多了内存可能会把无辜的 X 干掉), memory split 问题, 还有曾经的 32bit 1G lowmem patch(不过现在应该没人用了, 作者居然是 Con Kolivas :( )
@whoami
期待你多补充一些嘛
这个问题以前听基盘的朋友谈起过,说在redhat4上还存在,在redhat5上就修复了。看了你写的发现还不是那样的问题。
这个出现过Oracle进程被杀掉的情况。比较可怕。
03年的时候在做imu项目的时候出过这样的问题,服务程序有溢出,最夸张的一次是将sshd kill了,导致无法远程登录!
我这有台Slackware,非常重要的Mysql DB,上边也跑了应用程序,应用把内存和Swap吃光了,然后,mysql就自动重启了。dmesg下边又看到Free Swap为0,和oom-killer的字样
[60083042.176000] Swap cache: add 168883313, delete 168885711, find 92724386/111577334, race 32+7194
[60083042.176000] Free swap = 0kB
[60083042.176000] Total swap = 2048152kB
[60083042.176000] Free swap: 0kB
[60083042.192000] 1163263 pages of RAM
[60083042.192000] 933887 pages of HIGHMEM
[60083042.192000] 141947 reserved pages
[60083042.192000] 680 pages shared
[60083042.192000] 0 pages swap cached
[60083042.192000] 0 pages dirty
[60083042.192000] 0 pages writeback
[60083042.192000] 786656 pages mapped
[60083042.192000] 4073 pages slab
[60083042.192000] 3274 pages pagetables
[60083042.192000] oom-killer: gfp_mask=0x201d2, order=0
[60083042.192000] [] out_of_memory+0x2b/0xa9
[60083042.192000] [] __alloc_pages+0x1da/0x263
[60083042.192000] [] __do_page_cache_readahead+0xc1/0x135
[60083042.192000] [] filemap_nopage+0x149/0x2d5
[60083042.192000] [] do_no_page+0x93/0x2a2
[60083042.192000] [] dput+0x1b/0x119
[60083042.192000] [] __handle_mm_fault+0x147/0x253
[60083042.192000] [] do_page_fault+0x189/0x55f
[60083042.192000] [] sys_waitpid+0x13/0x17
[60083042.192000] [] do_page_fault+0x0/0x55f
[60083042.192000] [] error_code+0x4f/0x54
@bulletming
第一感觉可能是你的数据库连接开的太多了. 或许是什么突发的因素导致的
先检查一下吧
原作?