MySQL 的 CPU 达到 100% 情况复盘解析
一、业务场景及问题描述
网站总注册用户大约 6W,平时日活比较低,但是在活动的时候,高并发问题相继出现,当前,有一次活动,主要是给固定的 6 位 idol 进行投票应援,高并发问题也随之而来。
最直接的问题就是,在用户投票的时候突然不能投票,中间 mysql 大约宕机了 8min 左右。
二、网站服务背景描述
- web 服务:两台 web 服务器,均是 8 核 16G
- 一台 mysql5.6 服务器,4 核 8G,mysql 最大连接数 1500
- 一台 memcache 和一台 redis2.8
三、问题描述分析
- mysql 的 cpu 瞬间打满到 100%(平时最高不超过 40%),mysql 的 qps 瞬间达到 1w(平时不超过 500),磁盘使用和占用空间变小,慢查询次数极大增加
- web 服务器的负载瞬间增大到 5.7,平时不到 1
- nginx 报错:出现大量的 time out 和 too many open files 错误
19743#0: accept4() failed (24: Too many open files)
分析:
(1)nginx 出现 time out,说明 nginx 连接后端服务器比如 php 的时候,后端处理时间太长,导致出现超时
(2)出现超时问题,有两种通常的解决方式:一种就是分析后端为什么处理时间太长,一般是 mysql 慢查询问题,一种就是直接更改 nginx 超时时间,设置更长的超时时间。
(3)出现 too many files , 文件数打开太多,一方面是网站流量太大,一方面可以查看服务器的 max open files,可以通过 ulimit - a 命令查看最大打开文件数是 10w。
(4)出现 too many files,可以重新设置最大打开文件数,具体可以参考:https://learnku.com/articles/…
- 项目报错:出现大量的 mysql 连接错误
Next yiidbException: SQLSTATE[HY000] [2002] 连接超时 in /srv/www/vendor/yiisoft/yii2/db/Connection.php:624 Stack trace: #0 /srv/www/vendor/yiisoft/yii2/db/Connection.php(996): yiidbConnection->open() #1 /srv/www/vendor/yiisoft/yii2/db/Connection.php(983): yiidbConnection->getMasterPdo() #2 /srv/www/vendor/yiisoft/yii2/db/Command.php(253): yiidbConnection->getSlavePdo() #3 /srv/www/vendor/yiisoft/yii2/db/Command.php(1143): yiidbCommand->prepare(true) #4 /srv/www/vendor/yiisoft/yii2/db/Command.php(425): yiidbCommand->queryInternal(‘fetchColumn’, 0) #5 /srv/www/vendor/yiisoft/yii2/db/Query.php(463): yiidbCommand->queryScalar() #6 /srv/www/vendor/yiisoft/yii2/db/ActiveQuery.php(340): yiidbQuery->queryScalar(‘COUNT(*)’, Object(yiidbConnection))
分析:
(1)由此可以看到,整个服务的根源在于 mysql 出现了问题,一般可能就是瞬间的高并发,慢查询 sql 增多,导致 mysql 直接宕机,整个服务崩溃
(2)可以看到,mysql 的 qps 瞬间增大,cpu 直接打满,mysql 慢查询次数增加
(3)解决方式,主要是优化慢查询 sql,具体可以参考:https://my.oschina.net/sundas…
四、优化
- 对有慢查询 sql 进行索引等优化, 这是最主要的,一般出现 cpu 打满都是这个原因
- 在业务逻辑上进行优化,尽量避免复杂 sql,拆分成查询率更高的短 sql
- 慢查询逻辑中,能用 redis 的,尽量使用 redis
- show processlist 查看当前正在执行的 sql,看到有几条有异常的 sql 语句,发现从表中查询的数据过大,赶紧 kill 掉这些正在运行的语句