共计 1426 个字符,预计需要花费 4 分钟才能阅读完成。
排查 Mysql 忽然变慢的一次过程
本文源地址:排查 Mysql 忽然变慢的一次过程
上周客户说零碎忽然变得很慢,而且时不时的蹦出一个
404
和500
,弄得真的是很没面子,而凑巧出问题的时候正在深圳出差,所以始终没有工夫
看问题,始终到明天,才算是把问题起因找到。
定位问题
刚开始失去是零碎慢的反馈,没有将问题点定位到数据库上,查了半天服务是否失常(因为之前有一次 Dubbo 内存透露)。
在将应用服务日志查看了一遍后,没有发现任何异样,只是打了几个正告的日志。
于是又查看了业务运行时的日志,看到日志都提醒了一个 Lock wait timeout exceeded; try restarting transaction
的异样。
这时还是没有将重心放到数据库上,认为是代码的起因,导致事务始终没有提交。
从新将代码审阅了一遍,感觉应该不是代码逻辑的问题,而这个时候,Lock wait timeout exceeded; try restarting transaction
这个异样的日志越来越多。
认为是数据库层面出了问题,开始排查数据库。
寻找起因
因为咱们的数据库不是用的 云 RDS 版本
,是在一台 8 核 32G 的 AWS 上的装置版本。
应用 top
命令,查看到 Mysql 占用的 CPU 使用率高达 90% 左右。
心里一慌,感觉不妙,这样子高负载的 CPU 使用率,搞不好服务器都要宕掉。
于是拿出了仅有的一点 Mysql 基本知识,基本上这次只应用到了上面几个语句:
- 查看以后 Mysql 所有的过程
show processlist;
- 查看 Mysql 的最大缓存
show global variables like "global max_allowed_packet"
- 查看以后正在进行的事务
select * from information_schema.INNODB_TRX
- 查看以后 Mysql 的连接数
show status like 'thread%'
解决
依照下面的几个语句,一步一步跟踪定位下来。
show processlist;
下来,咱们就能够查看出以后所有的过程,并且失去最耗时的过程。
在以后数据库中,看到处于 Sleep
状态的 SQL 十分多,而这也是占用 CPU 过高的重大起因,休眠线程太多,于是配置了一个 wait_time_out
为 600 秒的一个解决方案。
为什么配置 600 秒,因为咱们利用超时工夫配置的最大工夫就是 600 秒,10 分钟,这里的配置须要依据业务来具体配置。
select * from information_schema.INNODB_TRX
执行这个语句,看到 Mysql 中大部分处于 Lock
的 SQL 是一条 update 的 SQL,而且还有一个单条件的 SQL,查问竟然耗时 4 分钟,很是诧异。
于是查看了这张表。
刚一关上构造,差点没忍住口吐芳香,竟然一个索引都没有,数据量超过 300W,没有索引查问基本上都要 4 分钟往上走。
于是筹备加上索引,在一阵漫长的期待中,索引终于加上去了。
show status like 'thread%'
索引加上去了之后,查看了一下以后 Mysql 的连接数,仿佛没有之前那么高了,预计是挤压的太多。
而后又查看了下服务器的 CPU 占用率,这次好了一点,从 1% 到 80% 来回跳动,没有呈现 90& 那么高的频率。
总结
Mysql 作为应用频率十分高的数据库,对于它的 SQL 调优真的是一门技术活,而且我的项目中的一些 SQL 看的也是想吐,这种调优起来真的难上加难。
其实 information_schema
这个数据库,外面的 Mysql 日志看起来比业务日志悦目的很多。