OOM Killer-被杀死的MySQL服务器


10

在我们的一名MySQL主服务器上,OOM Killer被调用并杀死了导致严重中断的MySQL服务器。以下是内核日志:

[2006013.230723] mysqld invoked oom-killer: gfp_mask=0x201da, order=0, oom_adj=0
[2006013.230733] Pid: 1319, comm: mysqld Tainted: P           2.6.32-5-amd64 #1
[2006013.230735] Call Trace:
[2006013.230744]  [<ffffffff810b6708>] ? oom_kill_process+0x7f/0x23f
[2006013.230750]  [<ffffffff8106bde2>] ? timekeeping_get_ns+0xe/0x2e
[2006013.230754]  [<ffffffff810b6c2c>] ? __out_of_memory+0x12a/0x141
[2006013.230757]  [<ffffffff810b6d83>] ? out_of_memory+0x140/0x172
[2006013.230762]  [<ffffffff810baae8>] ? __alloc_pages_nodemask+0x4ec/0x5fc
[2006013.230768]  [<ffffffff812fca02>] ? io_schedule+0x93/0xb7
[2006013.230773]  [<ffffffff810bc051>] ? __do_page_cache_readahead+0x9b/0x1b4
[2006013.230778]  [<ffffffff810652f8>] ? wake_bit_function+0x0/0x23
[2006013.230782]  [<ffffffff810bc186>] ? ra_submit+0x1c/0x20
[2006013.230785]  [<ffffffff810b4e53>] ? filemap_fault+0x17d/0x2f6
[2006013.230790]  [<ffffffff810cae1e>] ? __do_fault+0x54/0x3c3
[2006013.230794]  [<ffffffff812fce29>] ? __wait_on_bit_lock+0x76/0x84
[2006013.230798]  [<ffffffff810cd172>] ? handle_mm_fault+0x3b8/0x80f
[2006013.230803]  [<ffffffff8103a9a0>] ? pick_next_task+0x21/0x3c
[2006013.230808]  [<ffffffff810168ba>] ? sched_clock+0x5/0x8
[2006013.230813]  [<ffffffff81300186>] ? do_page_fault+0x2e0/0x2fc
[2006013.230817]  [<ffffffff812fe025>] ? page_fault+0x25/0x30

本机具有64GB RAM。

以下是mysql配置变量:

innodb_buffer_pool_size        = 48G
innodb_additional_mem_pool_size = 512M
innodb_log_buffer_size         = 64M

除了某些nagios插件和度量标准收集脚本之外,此计算机上没有其他任何运行。有人可以帮助我找出为什么调用OOM杀手以及如何防止它在将来被调用。有什么办法可以告诉OOM杀手不要杀死mysql服务器。我知道我们可以将oom_adj某个进程的值设置为很少,以防止它被OOM杀手杀死。但是还有其他方法可以防止这种情况。


2
内存使用率将高于48G+ 512M+,64M因为还有一些开销和其他结构需要考虑;某个地方有一个公式可以解决,但我现在找不到。不知道这是否会导致它崩溃64G。只是为了确保首先free确认64G可用?
frostschutz

@frostschutz:是的,免费命令显示64G。
pradeepchhetri

告诉OOM Killer不要杀死mysqld很可能只会将灾难延迟一小会儿。更好地修复您的配置。
scai

Answers:


25

Linux确实会过度使用内存。这意味着它允许进程请求比系统上实际可用更多的内存。当程序尝试使用malloc()时,内核会说“确定,您有内存”,但不要保留它。仅当进程将在此空间中写入内容时,才会保留内存。

要查看差异,您有2个指示器:虚拟内存和常驻内存。虚拟是进程请求的内存,常驻是进程真正使用的内存。

使用此系统,您可能会进入“超额预订”状态,内核授予的内存将超过可用内存。然后,当您的系统继续使用0字节的可用内存并进行交换时,他必须牺牲(杀死)一个进程以获取可用内存。

那就是OOM Killer付诸行动的时候。OOM根据他的内存消耗和许多其他因素(父母获得孩子得分的1/2来选择一个进程;如果它是根拥有的进程,则将得分除以4,依此类推。等等)。MM.org/OOM_Killer

可以通过修剪/proc/MySQL_PID/oom_adj文件来影响OOM评分。通过将其设置为-17,您的进程将永远不会被杀死。但是在此之前,您应该调整您的MySQL配置文件以限制MySQL内存的使用。否则,OOM Killer会杀死其他系统进程(例如SSH,crontab等),并且您的服务器将处于非常不稳定的状态,可能导致数据损坏,这比任何情况都更严重。

另外,您可以考虑使用更多交换。

[编辑]

您还可以通过以下两个sysctls更改它的过量使用行为:

vm.overcommit_memory
vm.overcommit_ratio

内核文档中所述

overcommit_memory:

该值包含一个标志,用于启用内存过量使用。

当此标志为0时,内核将尝试估计用户空间请求更多内存时剩余的可用内存量。

当该标志为1时,内核假装总是有足够的内存,直到它实际用完为止。

当此标志为2时,内核将使用“永不过量使用”策略来尝试防止内存过量使用。请注意,user_reserve_kbytes会影响此策略。

此功能非常有用,因为有很多程序会“分配” malloc()大量内存,以防万一。

默认值为0。

有关更多信息,请参见Documentation / vm / overcommit-accounting和security / commoncap.c :: cap_vm_enough_memory()。

overcommit_ratio:

当overcommit_memory设置为2时,不允许已提交的地址空间超过swap加上该物理RAM的百分比。看上面。

[/编辑]


1
这是正确的答案。我已经看到篇文章,约使用oom_score_adj解决这一点,但他们并不真正了解分数的机制。
3manuek
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.