一次因为 php-fpm 占用内过高,引起 MySQL 挂掉的总结 (1850 views)

gHOST

2018-06-29 11:41:04

一次服务挂掉的总结

现象

晚上10点多,运营的同事打电话过来,说服务器访问不了了。

打开电脑,访问 web 页面,报错:数据库不能访问。

排查

登陆服务器,再次启动 MySQL 启动不了,查看 MySQL 错误日志,重要的是这几行

2018-06-28 22:44:50 9113 [Note] InnoDB: Initializing buffer pool, size = 512.0M
InnoDB: mmap(549453824 bytes) failed; errno 12
2018-06-28 22:44:50 9113 [ERROR] InnoDB: Cannot allocate memory for the buffer pool
2018-06-28 22:44:50 9113 [ERROR] Plugin 'InnoDB' init function returned error.
2018-06-28 22:44:50 9113 [ERROR] Plugin 'InnoDB' registration as a STORAGE ENGINE failed.
2018-06-28 22:44:50 9113 [ERROR] Unknown/unsupported storage engine: InnoDB
2018-06-28 22:44:50 9113 [ERROR] Aborting

InnoDB 在分配内存的时候 报错:InnoDB: Cannot allocate memory for the buffer pool,内存不够。 用 top 命令查看空闲内存,的确是不到 512MB。

打开 /etc/my.cnf ,调小 innodb_buffer_pool_size 的值,从 512M 调到 256M,重新启动 MySQL,启动成功。服务恢复访问。

原因

服务器的配置是 8G 内存,不算 MySQL,空闲内存不到 512M,不是很正常,所以继续寻找内存占用率高的原因。

使用命令查看占用内存最多的10个进程

ps aux | sort -k4nr | head -10

发现除了第一的 MySQL,其他 9 个都是 php-fpm,查看 php-fpm 配置

pm.max_children = 150
pm.start_servers = 30
pm.min_spare_servers = 30
pm.max_spare_servers = 150

其中

  • pm.max_children 允许创建的最大子进程数
  • pm.start_servers 起始进程数(服务启动后初始进程数量)
  • pm.min_spare_servers 最小空闲进程数(清理空闲进程后的保留数量)
  • max_spare_servers 最大空闲进程数(当空闲进程达到此值时清理)

pm.max_children 就是服务器 PHP 访问能够支持的最大并发数,这个值要根据服务器的实际情况小心配置

相关知识点

查看进程内存使用情况

  1. ps
    ps aux | sort -k4nr | head -10
  2. top
    top

    在 top 界面下点击 M 以内存使用情况排序

  3. 查看php-fpm的进程个数
    ps -fe |grep "php-fpm"|grep "pool"|wc -l
  4. 查看每个php-fpm占用的内存大小
    ps -ylC php-fpm --sort:rss
  5. 查看单个php-fpm进程消耗内存的明细
    pmap $(pgrep php-cgi | head -1)

    这里可以根据需要减少不必要的模块加载。

php-fpm的参数优化

pm = dynamic #对于专用服务器,pm可以设置为static。#如何控制子进程,选项有static和dynamic。如果选择static,则由pm.max_children指定固定的子进程数。如果选择dynamic,则由下开参数决定:
pm.max_children #子进程最大数
pm.start_servers #启动时的进程数
pm.min_spare_servers #保证空闲进程数最小值,如果空闲进程小于此值,则创建新的子进程
pm.max_spare_servers #保证空闲进程数最大值,如果空闲进程大于此值,此进行清理

对于内存大的服务器(比如8G以上)来说,指定静态的max_children实际上更为妥当,因为这样不需要进行额外的进程数目控制,会提高效率。

对于内存小的服务器,使用动态方式。具体最大数量根据 内存/20M 得到。比如512M的VPS,建议pm.max_spare_servers设置为20。至于pm.min_spare_servers,则建议根据服务器的负载情况来设置,比较合适的值在5~10之间。

转自:https://www.jianshu.com/p/0aece01b8536

Mysql Innodb 引擎优化 参数(innodb_buffer_pool_size)

作用:

这个参数主要作用是缓存innodb表的索引,数据,插入数据时的缓冲

默认值:128M

专用mysql服务器设置的大小: 操作系统内存的70%-80%最佳。

设置方法:

my.cnf文件

innodb_buffer_pool_size = 6G

此外,这个参数是非动态的,要修改这个值,需要重启mysqld服务。

所以设置的时候要非常谨慎。

并不是设置的越大越好。设置的过大,会导致system的swap空间被占用,导致操作系统变慢,从而减低sql查询的效率。

参考:https://blog.csdn.net/lxpbs8851/article/details/9250439

相关知识文章