记一次生产环境CPU飙升100%的排查经历

一、前言

是这样的,我的项目是使用传统的Spring+SpringMVC+Mybatis架构的,有PC端后台管理系统,也有微信端H5网页,也就是一个微信公众号项目;项目部署采用Windows Server2008服务器,数据库使用·Mysql5.7·,最开始运行都非常的稳定,自动上线了一款功能:“微信打卡” 之后,规定每天只能打卡一次,并且规定时间点为6:00-9:00 这个时间段才能打卡,不在这个时间段则无法打卡,我的微信公众号用户有10万多,具体每天打卡量没有去具体的统计。

二、并发场景下产生的现象

6:00-9:00 这个时间段内,大量用户集中打卡,难免产生并发,服务器CPU持续飙升为100%,远程连接Windows服务器,鼠标卡死,无法操作,感觉整个系统瘫痪了,起初是以为生成的日志文件过多,于是每个月定时去删除上一个月的日志,最后发现不是,除了在6:00-9:00 这个时间段内外的其他时间,访问微信公众号H5网页,非常的流畅和稳定,页面响应也非常的快,只有在这个时间段内大量页面卡死,等待服务器响应,于是就有了后面的三次排查经历;

三、排查经历

1. 第1次CPU飙升100%的排查经历(未定位到核心)

第一次遇到这个问题,查看日志: Data source rejected establishment of connection, message from server : "Too many connections" 大概意思是连接数太多,于是我调整了mysql默认的连接数,调整至500,之前是150

并 发量过高,请求数过多,导致mysql连接数超过了最大连接数的阀值,现在是150,我先把阀值由150加到500

在这里插入图片描述
但是这个不是核心根本问题,于是开始了第二次排查

2. 第2次CPU飙升100%的排查经历(未定位到核心)

异常日志如下图:
在这里插入图片描述
通过查询资料,网上说是连接池的问题,修改对空闲连接池回收的时间,最开始默认为每3分钟回收一次,最后修改为没30分钟回收一次

     <!-- 超时时间;单位为秒。180秒=3分钟 -->
    <property name="removeAbandonedTimeout" value="180" />

在这里插入图片描述

3. 第3次CPU飙升100%的排查经历(SQL语句优化)

这次,服务器整个功能瘫痪了,点击都无法响应,大量请求阻塞,于是又开始了第三次的排次,这次排查以先定位慢查询为思路,然后挑出哪些慢查询SQL语句存在问题,然后对SQL语句进行优化处理。

  • 执行查询计划:
show full processlist; -- 列出全部SQL执行计划

查出有大量的SQL存在慢查询等待,state一直为Sending data
在这里插入图片描述
参数说明:

字段解释
idID标识,要kill一个语句的时候很有用
use当前连接用户
host显示这个连接从哪个ip的哪个端口上发出
db链接哪个数据库
command连接状态,一般是休眠(sleep),查询(query),连接(connect)
time连接持续时间,单位是秒
state显示当前sql语句的状态
info显示这个sql语句

其中state的状态十分关键,下表列出state主要状态和描述,这里只列举常见的几个,详细请百度:

字段描述
Locked被其他查询锁住了
Sending data正在处理SELECT查询的记录,同时正在把结果发送给客户端。
Sleeping正在等待客户端发送新请求.
  • 挑出具体的SQL语句执行执行计划EXPLAIN:
EXPLAIN SELECT
	f.nick_name AS nickName,
	f.headimgurl AS headImgUrl,
	f.open_id AS openId
FROM
  t_member m
LEFT JOIN t_follow f ON f.open_id = m.open_id WHERE m.green_card = '031011501705982345'
AND f.del_flag = '0'
AND m.del_flag = '0'

t_member 表的索引是普通索引 ,索引名字为member_openid_index, 索引的字段为open_id
t_follow 表的索引是唯一索引 , 索引名字为 唯一, 索引的字段为 open_id
从下面的执行结果图可以看出,t_follow表的唯一索引并没有使用上,而是使用的全表扫描,那么这就找到问题的核心了,一是找出为什么两个表左链接时,其中一张表的唯一索引没有使用上; 二是如何让t_follow表的所有使用上,不去全表扫描。
最后发现,光两张表连接字段加索引还不够,需要在m.green_card上也加一个索引即可,我加了普通索引

在这里插入图片描述
再次执行执行计划,就使用了索引查询:
在这里插入图片描述

  • 执行查询计划:
show full processlist; -- 列出全部SQL执行计划

数据库连接,都是空闲状态,等待客户端发送新的请求,没有产生慢查询的阻塞
在这里插入图片描述

  • 执行计划字段说明:
字段解释
id表示查询的类型
select_type表示选择标识符
table表示输出结果集的表
partitions表示匹配的分区
type表示表的连接类型
possible_keys表示查询时可能使用的索引
key表示查询时实际使用的索引
key_len表示索引字段的长度
ref表示列与索引的比较
rows表示扫描出的行数(估算的行数)
filtered表示按表条件过滤的行百分比
Extra表示执行情况的描述和说明

四、总结

项目生产环境的数据库一定要建索引,这个非常重要,而且需要根据重要的SQL语句分析索引该不该建、建哪些字段、建什么类型的索引,这些工作不可以忽略,以后我也会注重这个环节;

五、参考

  1. Mysql left join不使用索引问题总结
  2. 查一次left join没有走索引以及原因
  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Thinkingcao

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值