CentOS 7.4 MySQL被杀的问题

前段时间换了一个新的服务器终于从阿里的云虚拟主机升级为云服务器了,比较爽的事情就是终于可以自己管理自己的上线服务器了。以前公司有一台物理服务器部署在机房里面全部是我在管理,后续连续在这台服务器上面部署了redmine、gitlab、rap2还学习了一下linux编程,自认为有一定的实力进行线上的服务器管理了,感觉自己可以干运维的工作了(虽然以前的运维也是我在干)。有了这些经验的积累我觉得自己还是有资格使用自己的服务器并且完成部署。首先我将允虚拟主机上的博客项目无损迁移到目前使用的这台服务器上面而且配置了对应的环境,这些都是比较简单的事情但是没有过几天就发现一个奇怪的现象那就是我的mysql经常动不动就莫名其妙的没了,还是真正意义上面的没有了对应mysql服务的线程都没有了。最奇葩的事情是我尝试直接重新启动mysql得到就是一堆不明所以的报错。为了解决这个问题我开始调用我之前的运维经验并且尝试定位问题并解决。这里就将问题的发生、定位、解决整个思路都分享一下。

问题定位

首先是MySQL死掉作为整个事件的起点,访问mysql的运行日志没有发现任何报错,我还特地的开启了慢sql日志也没有发现有可能造成MySQL突然死掉的慢sql,所以我自然而然的分析到是我的MySQL可能有问题,毕竟CentOS7上面原生的yum源是没有mysql包的所以我安装的mysql是在网上找到的rpm包,我首先便怀疑是这个rpm包可能不是官方正式的版本可能是一个测试版什么的。所以我做的第一件事情就是去官网下载源码包然后自己手动编译安装。 完成之后重新同步一下源数据库的数据运行没有超过两天发生了相同的情况还是莫名其妙的消失了。

这就比较伤了说明不是mysql自己的问题那就只能是其他的什么东西把mysql给杀了,然后按照系统运行机制来讲如果不是mysql自己退出的话那只能是系统相同级别权限的什么东西把mysql给杀了所以立刻开始查找系统的运行日志终于找到了mysql被杀掉的原因:

Dec  3 20:57:33 izbp19z5o9dc912nh48x0az kernel: Killed process 865 (mysqld) total-vm:1145548kB, anon-rss:202816kB, file-rss:0kB, shmem-rss:0kB
Dec  3 20:57:33 izbp19z5o9dc912nh48x0az systemd: mysqld.service: main process exited, code=killed, status=9/KILL

系统内存不足导致centos自动开始清除占用内存最大的程序那就是mysql。但是我立刻反应过来不对头,我的服务器是1核1G的常规性没有按照我的博客访问情况mysql因为有缓存限制它最多吃个200M内存不得了但是系统内存不足是只有在无法分配内存到系统关键应用才会发送的错误这个事情就比较蹊跷。那么按照centos占用系统300M左右的内存情况来看我剩下的500M到底是被什么东西给吃掉了?立刻top一下发现一个可怕的情况php-fpm居然开启了二十多个线程正在跑着平均每一个占用了系统2%左右的内存,free m一下发现系统剩余的可用内存不足16M了。妈的要是一开始就去查看系统内存情况就不需要绕这一下离开就可以定位到问题,看来还是经验不足。

解决问题

发现了问题就必须想办法解决,其实php-fpm就是php自己的一个CGI组件这个东西就是一个低级的FASTCGI具备一个消息队列与线程池。问题在与它的线程池产生的线程数量太多了我的乞丐服务器根本承受不住。这里必须要说一下以前的项目是如何部署的,之前的项目采用的是宝塔的管理后台,这个东西确实方便但是它也把系统的内存进行了一个限制,反正宝塔在这些低配服务器上面卡的一逼之后我们才开始自己手动搭建环境间服务器管理的。既然找到了问题发生的原因我们就只需要解决它了。首先就是百度查看了一下资料之后发现php-fpm是可以通过配置文件进行线程池的限制的具体方法我就直接写在代码块里面了:

vi /etc/php-fpm.d/www.conf
//编辑php-fpm的配置文件

这里是对应配置文件里面的注释是对线程池配置项的一些描述

; Choose how the process manager will control the number of child processes.
; Possible Values:
;   static  - a fixed number (pm.max_children) of child processes;
;   dynamic - the number of child processes are set dynamically based on the
;             following directives. With this process management, there will be
;             always at least 1 children.
;             pm.max_children      - the maximum number of children that can
;                                    be alive at the same time.
;             pm.start_servers     - the number of children created on startup.
;             pm.min_spare_servers - the minimum number of children in 'idle'
;                                    state (waiting to process). If the number
;                                    of 'idle' processes is less than this
;                                    number then some children will be created.
;             pm.max_spare_servers - the maximum number of children in 'idle'
;                                    state (waiting to process). If the number
;                                    of 'idle' processes is greater than this
;                                    number then some children will be killed.
;  ondemand - no children are created at startup. Children will be forked when
;             new requests will connect. The following parameter are used:
;             pm.max_children           - the maximum number of children that
;                                         can be alive at the same time.
;             pm.process_idle_timeout   - The number of seconds after which
;                                         an idle process will be killed.
; Note: This value is mandatory.

pm.max_children 的默认值为50,每一个进程占用1%-2.5%的内存,加起来就耗费什么内存都没有了,所以我们需要将其值调小,我由于使用的是乞丐版的服务器所以直接给到了15个子线程。pm.max_spare_servers : 该值表示保证空闲进程数最大值,如果空闲进程大于此值,此进行清理 pm.min_spare_servers : 保证空闲进程数最小值,如果空闲进程小于此值,则创建新的子进程,这两个值均不能不能大于 pm.max_children 值,通常设置 pm.max_spare_servers 值为 pm.max_children 值的60%-80%。最后,重启php-fpm

systemctl restart php-fpm

这样一来服务器基本上在全部线程跑起来之后都还有100M以上的内存空闲空间。这样就比较稳,自从我这样配置修改之后服务器的mysql就再也没有死过了。

总结

其实我的总结就只有一句话:PHP就是一个垃圾!!

留下回复