一次解决LNMP主机反复宕机问题的记录

新购的一台阿里云主机,几乎每天都会发生MySQL自动停止服务。主机其他部分看来运行都正常,怀疑是哪里设置的不对,但我装完这台LNMP改的默认设置不多,之前也并没有碰到过类似的问题。既然是MySQL停止服务,那么就从MySQL这里找问题,搜索了一个多小时,发现MySQL宕机有很多可能性,一时无法确定。但解决此类问题的关键都是查看错误日志开始。

命令行进入本地MySQL,之后输入密码

mysql -hlocalhost -uroot -p

之后进入提示符mysql>

查看错误日志的位置

mysql> show variables like '%log_error%';

此时获取到了文件位置。查看日志后,发现大部分重复片段是这样的:

2017-07-26 04:34:03 7617 [Note] Plugin 'FEDERATED' is disabled.
2017-07-26 04:34:03 7617 [Note] InnoDB: Using atomics to ref count buffer pool pages
2017-07-26 04:34:03 7617 [Note] InnoDB: The InnoDB memory heap is disabled
2017-07-26 04:34:03 7617 [Note] InnoDB: Mutexes and rw_locks use GCC atomic builtins
2017-07-26 04:34:03 7617 [Note] InnoDB: Memory barrier is not used
2017-07-26 04:34:03 7617 [Note] InnoDB: Compressed tables use zlib 1.2.3
2017-07-26 04:34:03 7617 [Note] InnoDB: Using CPU crc32 instructions
2017-07-26 04:34:03 7617 [Note] InnoDB: Initializing buffer pool, size = 128.0M
InnoDB: mmap(137363456 bytes) failed; errno 12
2017-07-26 04:34:03 7617 [ERROR] InnoDB: Cannot allocate memory for the buffer pool
2017-07-26 04:34:03 7617 [ERROR] Plugin 'InnoDB' init function returned error.
2017-07-26 04:34:03 7617 [ERROR] Plugin 'InnoDB' registration as a STORAGE ENGINE failed.
2017-07-26 04:34:03 7617 [ERROR] Unknown/unsupported storage engine: InnoDB
2017-07-26 04:34:03 7617 [ERROR] Aborting


其中第二行和倒数第五行、倒数第七行反复提到“buffer pool”,看上去和内存有关,但不敢确定,于是借助阿里云的文档库找了一下答案:
https://help.aliyun.com/knowledge_detail/41106.html#内存配置

文档建议”innodb_buffer_pool_size”、”key_buffer_size”都设置成主机实际剩余内存的一半。

找到MySQL的配置文件my.cnf,找到这两行:
innodb_buffer_pool_size = 128M
key_buffer_size = 32M

居然默认设置是那么小,尝试调大成256M和64M,重启一下MySQL,等了两天服务器似乎无问题,但是到第三天又宕机了。


继续搜索解决方案,在国外网站中提到MySQL5.6的默认配置对内存要求较大会导致经常宕机,很符合我碰到的现象,参考这里https://askubuntu.com/questions/457923/why-did-installation-of-mysql-5-6-on-ubuntu-14-04-fail/457932#457932
因此尝试
max_connections = 500
改成100

再次重启,稳定了几天后,又发现同样报错。


谷歌了一下,又感觉之前是误解了innodb_buffer_pool_size的设置,减小改成64M再试试看,但是过了几天又是老毛病。


由于我几乎每年都会新增一台云主机放新的网站,每台主机都装当年最新版本的lnmp运行环境,感觉问题还是在MySQL的配置里,在多次对比之前几台主机的配置之后,发现占内存大的那台主机启用了InnoDB,两台较早的主机则没有。回想起来lnmp从1.3版开始鼓励开启InnoDB,并且日志报错也大量出现InnoDB关键词,这很有可能是导致内存消耗过大的罪魁。
于是继续修改配置文件my.cnf

[mysqld]
default-storage-engine = MyISAM
…
skip-innodb

再度重启主机后,发现占用内存一下子少了很多。但好景不长,过了不久又内存用满。


继续搜索解决办法,在阿里云论坛里找到关闭MySQL日志的办法,在my.cnf里面注释掉这两句:

#log-bin=mysql-bin
#binlog_format=mixed

过了一段时间还是老问题。现在想来这个是为了防止日志文件占用过大的硬盘容量而设的,并非我碰到的问题,所以很快又改了回来。


经过以上那么多优化,觉得MySQL应该已经没什么可以加强的了,改来改去无非是为了优化MySQL的性能,但对于宕机这种硬冲突,恐怕问题还是处在了别处,于是干脆尝试关闭MySQL,发现居然内存占用率还是一直飙升,这下感觉真应该从别的地方入手了,根据这篇文章的提示给php-fpm.conf 增加一条进程请求服务数的限制
pm.max_requests = 800

重启经过观察,问题依旧。


既然开始修改php-fpm.conf,索性对比另一台稳定运行的ECS里的这个文件,对一些选项进行重新设置:

pm.max_children = 20
pm.start_servers = 10
pm.min_spare_servers = 10
pm.max_spare_servers = 20

改成:

pm.max_children = 10
pm.start_servers = 2
pm.min_spare_servers = 1
pm.max_spare_servers = 6

重启后等待了两天,居然内存占用稳定在60%以内,这是从来没有过的,问题终于得到了解决。

总结:服务器内存告警一般最先停止服务的就是MySQL,因此很容易让人觉得是MySQL出了问题。从错误日志入手排查是没错的,至少这次就很快确定了是内存不够。但究竟是什么原因导致了内存不够,我还是饶了很大的圈子。幸好我有好几台主机同时运行,虽然装了不同版本的lnmp和MySQL版本,但互相参考服务器设置还是很有帮助的。这次我发现同样两台同样配置的主机,一年前装了lnmp1.3+MySQL5.5的那台,和这次出问题的那台(为了更进一步参考配置也装了lnmp1.3+MySQL5.5),居然php-fpm.conf和my.conf的默认设置都有很大的不同,最后还是通过复制一年前那台主机的php-fpm.conf设置才解决了问题。这很有可能是lnmp本身的一个坑,作者在过了那么长时间后,调整了安装包的默认设置,反而导致在我的1核2G云主机上跑不起来。

本站所有文章均为原创,欢迎转载,请注明文章出处:https://blog.brain1981.com/1680.html。百度不可信,搜索请谨慎。技术类文章一般都有时效性,本人习惯不定期对自己的博文进行修正和更新,因此请访问出处以获取本文的最新版本。

关注我们的微信公众号-JennyStudio 本站记录了近几年的工作中遇到的一些技术问题和解决过程,“作品集”还收录了本人的大部分作品展示。除了本博客外,我们的工作室网站 – JennyStudio,内有更多作品回顾和展示。
您也可以扫描左边的二维码,关注我们的微信公众号,在微信上查看我们的案例。

1 关于 “一次解决LNMP主机反复宕机问题的记录” 的评论

发表评论

电子邮件地址不会被公开。 必填项已用*标注