热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

压力测试过程中MySQL服务CPU占用率过高的问题排查思路

〇、经验总结:在关注业务接口的TPS时,也要关注数据库服务器的QPS。如果一个业务流程里包含多条查询,那么业务接口TPS的上升对数据库服务器QP

〇、经验总结:

  • 在关注业务接口的TPS时,也要关注数据库服务器的QPS。如果一个业务流程里包含多条查询,那么业务接口TPS的上升对数据库服务器QPS的放大效应会很明显。
  • 如果查询结果集不大,尽量使用一条查询语句,通过子查询返回多个结果集,避免将多个结果集拆分成多次数据库查询,否则会造成过多的数据库连接/查询操作,消耗IO资源,降低TPS,提高CPU占用率。
  • 在业务代码中,尽量避免在循环语句里写数据库查询。
  • 依据SQL语句的使用频率来建立索引,查询条件字段顺序按照联合索引的字段顺序来写(从左到右的匹配顺序)
  • 关注慢查日志

一、背景说明

接着上一篇Grpc性能调优的文章继续写,我们这次压测的是一个查询用户群组列表信息的接口,该接口里需要查询某个用户的所有群组信息,包括每个群组的名称、成员数量等。
经过之前对业务机器的JVM参数等进行优化后,现在已经不存在业务机器的频繁GC、CPU占用率过高、TPS上不去等问题了。但是我们遇到了两个新问题:在业务接口并发50、TPS600左右时,压测接口出现了超时错误,而且数据库服务器CPU占用率超过了93%

二、测试过程

数据准备:

  • t_info_group群组表:
    压力测试过程中MySQL服务CPU占用率过高的问题排查思路

  • t_info_group_member群组成员表:
    压力测试过程中MySQL服务CPU占用率过高的问题排查思路

数据约定:测试数据中,每个群组里面有3000个成员;每个成员有20个群组。

1、第一次压测

我们首先进行一次摸底测试,使用两台压测机器共同发起300个并发,持续压测2分钟。(如果只用一台压测机发起300个并发,会由于机器端口受限,TPS超过5W后不能发起新请求,压测机将报错)
(1)数据库连接池配置
c3p0.initialPoolSize=15
c3p0.minPoolSize=15
c3p0.acquireIncrement=10
c3p0.maxPoolSize=32
(2)数据库慢查日志、数据库服务器监控指标
压力测试过程中MySQL服务CPU占用率过高的问题排查思路

top命令显示CPU使用率超过了91%,而且慢查日志一直在刷!
通过分析慢查日志里面的SQL语句,以及对应的数据库表,发现查询语句中有“where a=.. and b=.. and c=..”,但是有一个联合索引的字段是“a, c"。根据联合索引的匹配规则,这条sql用不了索引,导致慢查。经过将索引更换成"a, b, c",单条sql查询效率提高一倍。

2、第二次压测

使用两台压测机器共同发起50个并发,持续压测2分钟。
(1)其他配置均不做改变。
(2)数据库慢查日志、数据库服务器监控指标
经过上述调整,慢查日志没有了,但是CPU使用率依然还是超过了90%。这是一个不能容忍的数据,如果并发继续提高,数据库服务器很快将被撑爆。
压力测试过程中MySQL服务CPU占用率过高的问题排查思路

压力测试过程中MySQL服务CPU占用率过高的问题排查思路

由于其他涉及到sql查询的接口在压测时都没有出现过CPU占用率这么高的情况,所以我们排除了数据库服务器安装配置的问题。
我们开始思考出现问题的可能原因:

  • 数据库连接池等参数配置有缺陷,导致连接池不够用,一直在建立新的连接。
  • 业务代码逻辑可能存在缺陷,导致查询语句消耗过多IO或内存资源。
  • 并发数量高,数据库服务器CPU正常就需要占用这么多。(这是最无奈最不想接受的结局)
    我们先查看show processlist; 的结果,发现有很多连接其实是空闲的,也就是说目前的连接池已经够用了。
    而当我们把连接池尝试放大,配置改为:
    c3p0.initialPoolSize=20
    c3p0.minPoolSize=20
    c3p0.acquireIncrement=20
    c3p0.maxPoolSize=128
    在这个配置下,对CPU的占用率没有丝毫影响。那么排除连接池配置的问题。
    那有没有可能是在当前并发量条件下,就需要消耗这么多的CPU呢?
    我们对比了另一个涉及到SQL查询的接口,在60个并发下,那个接口的TPS达到了1100,而现在压测的接口,TPS只有600。那么在同等并发下,相同的查询语句复杂度和查询结果数据量条件下,现在压测的接口不仅TPS低,还占用了过多的CPU,可能就不是数据库的问题。这就排除了因并发量高而必然导致CPU占用率超过90%的假设。
    我们继续看数据库服务器的监控指标,使用阿里的orzdba脚本监控MySQL服务器。
    当前压测接口的MySQL服务器指标数据:
    压力测试过程中MySQL服务CPU占用率过高的问题排查思路

对照接口的指标数据:
压力测试过程中MySQL服务CPU占用率过高的问题排查思路

从上述两个对比图可以看到,当前压测接口的数据库QPS高达3000。对比数据汇总一下,可以看出一些问题:
当前接口:
并发:60,TPS:600,数据库CPU:92%,数据库QPS:3000
对照接口:
并发60,TPS:1000,数据库CPU:20%,数据库QPS:1400
当前压测接口处理更耗时,可能原因是一次接口业务里涉及到了多次数据库操作。
那么接下来就是排查业务代码里的数据库操作了。进行code review!
核心业务伪代码:
//查询用户的群组列表
List groupList = groupDao.selectGroups(userId);
for(Dto dto:groupList){
//查询每个群组的用户数,会循环20次!
int userNumber = groupDao.getGroupNumber(dto.getAsIong(groupId));
}

这段代码怎么这么别扭?第一个查询已经去查询群组信息了,还要用for循环去遍历20次统计每个群组用户数??
这样操作的话,一次接口请求将操作很多次的数据库查询,并带来更多网络、IO操作。那么CPU占用率过高的问题很可能是这个情况导致的。
我们的优化措施是优化groupDao.selectGroups(userId)对应的查询语句,使用子查询返回用户的群组列表和每个群组的用户数,去掉for循环。

3、第三次压测

使用两台压测机器共同发起50个并发,持续压测2分钟。
(1)其他配置均不做改变。
(2)数据库慢查日志、数据库服务器监控指标
数据库慢查日志没有提示慢查SQL语句,数据库服务器CPU占用率稳定在80%以下,数据库QPS提高到了近7000!这个优化效果可以说是非常的明显了。

压力测试过程中MySQL服务CPU占用率过高的问题排查思路

4、留给我的疑问

也许有人会问:代码优化后数据库的QPS比之前更高了,那CPU使用应该更多啊,但是为什么数据库的CPU占用率反而降下来了呢?这是为什么呢?[这个问题,其实我也没有想明白,有知道原因的朋友欢迎留言讨论。]
对于这个问题,我最近一直在思考,并查阅相关的资料,突然从接口优化前后的性能数据上可以看到:优化前,业务接口的TPS才600,数据库QPS才3000,而优化后的业务接口TPS达到了1100,几乎翻倍,同时数据库QPS达到了6000,也翻倍了,但数据库CPU使用率反而降低了。从这几个数据可以得到这样一条结论:接口TPS的增长,自然导致了数据库QPS的同级别增长,说明在优化前和优化后,数据库的压力瓶颈还远没有达到,那么数据库服务器CPU使用率的飙高,也不是由于SQL处理导致的!
数据库服务器的资源消耗,除了SQL执行、磁盘IO,其实还有网络连接。
优化前的代码里,一次TPS会进行多次数据库连接并提交SQL查询请求,这个操作带来的网络连接消耗也是非常可观的,优化后的代码里,一次TPS就进行一次数据库连接并提交SQL查询请求,资源消耗降低了很多。

  • 接口优化前:
    并发:60,TPS:600,数据库CPU:92%,数据库QPS:3000
    压力测试过程中MySQL服务CPU占用率过高的问题排查思路
    压力测试过程中MySQL服务CPU占用率过高的问题排查思路

  • 接口优化后:
    并发:60,TPS:1100,数据库CPU:低于80%,数据库QPS:6000
    压力测试过程中MySQL服务CPU占用率过高的问题排查思路

推荐阅读
  • 压力测试_单节点数据库的压力测试
    mysqlslap是mysql自带的基准测试工具,优点:查询数据,语法简单 ... [详细]
  • TiDB | TiDB在5A级物流企业核心系统的应用与实践
    TiDB在5A级物流企业核心系统的应用与实践前言一、业务背景科捷物流概况神州金库简介二、现状与挑战神州金库现有技术体系业务挑战应对方案三、TiDB解决方案测试迁移收益问题四、说在最 ... [详细]
  • 篇首语:本文由编程笔记#小编为大家整理,主要介绍了软件测试知识点之数据库压力测试方法小结相关的知识,希望对你有一定的参考价值。 ... [详细]
  • 本文介绍了如何使用php限制数据库插入的条数并显示每次插入数据库之间的数据数目,以及避免重复提交的方法。同时还介绍了如何限制某一个数据库用户的并发连接数,以及设置数据库的连接数和连接超时时间的方法。最后提供了一些关于浏览器在线用户数和数据库连接数量比例的参考值。 ... [详细]
  • 本文详细介绍了MysqlDump和mysqldump进行全库备份的相关知识,包括备份命令的使用方法、my.cnf配置文件的设置、binlog日志的位置指定、增量恢复的方式以及适用于innodb引擎和myisam引擎的备份方法。对于需要进行数据库备份的用户来说,本文提供了一些有价值的参考内容。 ... [详细]
  • 本文详细介绍了Linux中进程控制块PCBtask_struct结构体的结构和作用,包括进程状态、进程号、待处理信号、进程地址空间、调度标志、锁深度、基本时间片、调度策略以及内存管理信息等方面的内容。阅读本文可以更加深入地了解Linux进程管理的原理和机制。 ... [详细]
  • 图解redis的持久化存储机制RDB和AOF的原理和优缺点
    本文通过图解的方式介绍了redis的持久化存储机制RDB和AOF的原理和优缺点。RDB是将redis内存中的数据保存为快照文件,恢复速度较快但不支持拉链式快照。AOF是将操作日志保存到磁盘,实时存储数据但恢复速度较慢。文章详细分析了两种机制的优缺点,帮助读者更好地理解redis的持久化存储策略。 ... [详细]
  • MyBatis多表查询与动态SQL使用
    本文介绍了MyBatis多表查询与动态SQL的使用方法,包括一对一查询和一对多查询。同时还介绍了动态SQL的使用,包括if标签、trim标签、where标签、set标签和foreach标签的用法。文章还提供了相关的配置信息和示例代码。 ... [详细]
  • 先看一段错误日志:###Errorqueryingdatabase.Cause:com.mysql.jdbc.exceptions.jdbc4.MySQLNonTransie ... [详细]
  • 本文介绍了关系型数据库和NoSQL数据库的概念和特点,列举了主流的关系型数据库和NoSQL数据库,同时描述了它们在新闻、电商抢购信息和微博热点信息等场景中的应用。此外,还提供了MySQL配置文件的相关内容。 ... [详细]
  • 本文介绍了H5游戏性能优化和调试技巧,包括从问题表象出发进行优化、排除外部问题导致的卡顿、帧率设定、减少drawcall的方法、UI优化和图集渲染等八个理念。对于游戏程序员来说,解决游戏性能问题是一个关键的任务,本文提供了一些有用的参考价值。摘要长度为183字。 ... [详细]
  • 微服务之总体架构篇
    一、单体架构存在的问题缺点:1、难以维护:当单体应用业务不断迭代后代码量非常臃肿,模整个项目非常复杂,每次更改代码都可能带来新的bug;2、部署项目麻烦:庞大之后项目部署效率 ... [详细]
  • SQLServerDBA十大必备工具让生活轻松点(转)
    曾经和一些DBA和数据库开发人员交流时,问他们都用过一些什么样的DB方面的工具,大部分人除了SSMS和Profile之外,基本就没有使用过 ... [详细]
  • 【2021Java最新学习路线】开启mysql远程连接
    前言面试技巧另外开篇再说,先上面试干货吧。面试的题目并不一定有严格的顺序关系,有的是从前一个问题延伸而来,(探究的是一个知 ... [详细]
  • 本文讨论了在数据库打开和关闭状态下,重新命名或移动数据文件和日志文件的情况。针对性能和维护原因,需要将数据库文件移动到不同的磁盘上或重新分配到新的磁盘上的情况,以及在操作系统级别移动或重命名数据文件但未在数据库层进行重命名导致报错的情况。通过三个方面进行讨论。 ... [详细]
author-avatar
11
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有