国庆假期刚过,还在假期后遗症中。公司的内部测试服务器配的MySQL不给了,给我挂了好几次。
查看一下系统日志:
1 | tail -1000 /var/log/messages | grep mysqld |
发现Out of memory: Kill process 129382 (mysqld) score 9 or sacrifice child
1 | Out of memory: Kill process 129382 (mysqld) score 9 or sacrifice child |
大概就知道是内存不足导致的。心想着这台服务器硬件太低了吧,想着换一台机器算了。
但是怀着一探究竟的精神,百度了一下这个错误,果然发现一个叫做OOM Killer的东西。
Linux 内核有个机制叫OOM killer(Out Of Memory killer),该机制会监控那些占用内存过大,尤其是瞬间占用内存很快的进程,然后防止内存耗尽而自动把该进程杀掉。
OOM Killer的触发
下面我们模拟一个场景,用一个很吃内存的进程,耗尽所有内存
先查看我们的内存
1 | [root@centos65 ~]# free -m |
显示我有1G的内存,可用内存有900M左右,交换分区有2G
现在执行dd吃掉内存:
1 | [root@hostname www]# dd if=/dev/zero of=/dev/null bs=2000M |
再次查看内存情况:
1 | [root@centos65 ~]# free -m |
当内存没有了,就会使用swap虚拟内存,此时系统已经非常慢了。
关掉交换分区1
swapoff -a
再次查看内存:
1 | [root@centos65 ~]# free -m |
swap已经为0, 再次执行dd吃掉内存:
1 | [root@hostname www]# dd if=/dev/zero of=/dev/null bs=890M |
发现进程被Kill掉了
查看日志:
1 | tail -f /var/log/messages | grep "Out of memory" |
MySQL关于对SWAP分区的思考
使用交换分区能够防止mysqld进程被kill掉,但是由于当系统内存不足了,使用swap会将一些虚拟内存写到磁盘的交换区中这样就会发生内存交换。一旦发生内存交换,对mysql会有灾难性的影响。
所以究竟要不要使用swap,其实还是有争议的,个人感觉不要使用比较好:
- 公有云上的机器基本都没有交换分区
- 机器的内存应该在超过一定的百分比后的时候进行告警,及时处理,就可以避免mysqld因内存不足被kill的问题
关闭swap可以使用设置内核参数: vm.swappiness=0;
延伸阅读
更多防止oom killer杀掉mysqld进程的方案:
参考: