持续交付 手把手教你排查线上环境 Mysql 性能问题

灬囖 · 2023年06月14日 · 2691 次阅读

一、背景:

在巡检线上环境的时候,随便点击了一个报告页面,导致页面直接转圈卡死,等了 5 分钟才反应过来。起初还以为是网络问题导致的,就没有太在意,过了一会,又尝试了一下,还是慢,又对比了一下其它网页,发现其它网页都是正常的,只有这个页面的列表很慢。好巧不巧,我这该死的好奇心又被勾起来了,开始探寻之路.......

二、定位问题:

既然是页面卡顿,那么我们从下面几个方面来逐一排查,定位问题。

  • 网络延迟问题
  • 服务器配置问题
  • 接口逻辑问题
  • 数据库的问题

2.1 网络延迟问题

首先是想到的肯定是网络问题,但是,线上环境使用的是公司的内网,按道理来讲,出现这种可能性很低,于是我就找到负责网络的人员,得知,网络是没有问题的。我也从其他小伙伴那里尝试去访问,但最终结果是,访问其它页面都没有问题,唯独之后这个页面慢。所以网络这个问题也就排除掉了。

2.2 服务器配置问题

排除掉了网络问题,那么来看一下服务器配置是否有问题,通过堡垒机( JumpServer 推荐一下,挺好用的)登录到服务器,通过一番操作之后,服务器配置是 8c32g,磁盘 400g,磁盘使用率 18%, 内存使用率 65%,有持续跟踪了一下,点击页面的时候,cpu 和内存并没有出现明显的飙升现象。所以,这么一圈分析下来,服务器配置的问题也就排除了。

2.3 接口逻辑问题

  1. 排除了外部因素,那么要分析一下系统本身的问题了,因为是列表查询,所以说,当接口逻辑非常复杂的时候,各种计算聚合的时候,也会出现这种问题。所以就从代码层面排查一下,问了研发的同事,看了一下接口处理的逻辑,并没有发现什么问题,况且,因为是列表查询,还有分页处理,也就是每次只查询 10 条数据展示出来。
  2. 通过研发同事给我的结论,那么就排除了接口逻辑的问题。

2.4 数据库问题

  1. 既然把其他可能性都排除了,那么只剩下数据库的问题了,我们把重点放在数据库这边来。
  2. 首先还是接口,因为查询的时候肯定要跟数据库进行交互的,所以就要考虑是否使用索引,sql 语句是否可以优化,是否有慢查询等。
  3. 跟研发同事沟通,拿到了完整的 sql 语句,在数据库里面查询了一下,发现直接在数据库里面查询就很慢,要响应 2 分钟的样子。
  4. 接着又查询了一下总的数据量,发现目前表中有 20 多万条数据,这个数据量算是正常范围之内的。架构上暂时不需要调整。
  5. 根据上面查询,发现 sql 查询慢的问题,怀疑是没有用到索引,就用 explain 执行了一下,结果如下。

因为是生产数据,不太方便放出原图,这边就放一张模拟的看下

通过图中显示出,这条 sql 中已经使用到了索引,所以也不是索引的问题。

  1. 那么既然使用到了索引,那么会不会是 sql 的问题呢?此方案我也进行了验证,sql 是没问题的,通过几次查询,都是一样的结论。
  2. 排查到这里,又陷入了深思..... 感受到了江郎才尽,于是就处于混沌状态中,起来喝杯水,看看窗外景色,放松一下大脑,在经过一系列思想斗争之后,终于,还是决定做一件大事——从头开始排查。
  3. 那么到此,大方向已经确认了,数据库方向的问题,具体是哪里的问题?请继续跟着我走。 # 三、分析问题: 定位到了大方向,接下来就好办了,先从服务器硬件排查,数据库是独立部署的,配置是 4c8g 的,当时内存使用率已经达到了 90% 以上了,所以就加了配置,改为 4c16g 的了。

添加了之后,然并卵...... ,该慢的还是慢。

服务器配置也添加了,索引、慢 sql 也排查了,都没有问题,那么问题在哪里呢?以重新开始的态度继续排查,就排查到了一个重要的指标—— mysql 的缓存池使用率

这个指标很有用,简单说一下:
当我们使用 InnoDB 存储引擎时,它会将数据缓存在内存中,以提高查询性能。以下是关于 InnoDB 缓存的三个重要概念:


1. InnoDB缓存读命中率:指在查询数据时,InnoDB引擎从缓存中读取数据的比率。如果数据已经存在于缓存中,InnoDB就会从缓存中读取,而不是从磁盘中读取。因此,高缓存读命中率表示查询性能较好。
- 计算方法:InnoDB缓存读命中率 = (1 -(Innodb_buffer_pool_reads/Innodb_buffer_pool_read_requests)) * 100%
2. InnoDB缓存使用率:指InnoDB缓存中已经使用的内存比例。因为InnoDB缓存的内存大小是有限的,所以高缓存使用率表示需要增加缓存大小,以避免频繁的磁盘读写。
- 计算方法:InnoDB缓存使用率 = (Innodb_buffer_pool_pages_data / Innodb_buffer_pool_pages_total) * 100%
3. InnoDB脏块率:指InnoDB缓存中已修改但尚未写回磁盘的数据块比例。因为脏块需要写回磁盘,所以高脏块率会影响性能。
- 计算方法:InnoDB脏块率 = (Innodb_buffer_pool_pages_dirty / Innodb_buffer_pool_pages_total) * 100%

综上所述,以下是关于 InnoDB 缓存的三个重要概念及其计算方法的列表:

概念 定义 计算方法
InnoDB 缓存读命中率 InnoDB 引擎从缓存中读取数据的比率 (1 - (Innodb_buffer_pool_reads / Innodb_buffer_pool_read_requests)) * 100%
InnoDB 缓存使用率 InnoDB 缓存中已经使用的内存比例 (Innodb_buffer_pool_pages_data / Innodb_buffer_pool_pages_total) * 100%
InnoDB 脏块率 InnoDB 缓存中已修改但尚未写回磁盘的数据块比例 (Innodb_buffer_pool_pages_dirty / Innodb_buffer_pool_pages_total) * 100%

查询命令:

SHOW GLOBAL STATUS LIKE 'Innodb_buffer_pool_read_requests';
SHOW GLOBAL STATUS LIKE 'Innodb_buffer_pool_reads';
SHOW GLOBAL STATUS LIKE 'Innodb_buffer_pool_pages_total';
SHOW GLOBAL STATUS LIKE 'Innodb_buffer_pool_pages_data';
SHOW GLOBAL STATUS LIKE 'Innodb_buffer_pool_pages_dirty';

四、总结:

  1. InnoDB 缓存是 MySQL 中一个非常重要的性能优化参数,可以提高查询性能。
  2. InnoDB 缓存的三个重要概念包括:InnoDB 缓存读命中率、InnoDB 缓存使用率和 InnoDB 脏块率。
  3. InnoDB 缓存读命中率越高,表示查询性能越好;InnoDB 缓存使用率越高,表示系统内存使用率越高;InnoDB 脏块率越高,表示需要写回磁盘的数据越多,会影响性能。
  4. 可以使用 MySQL 命令来查询 InnoDB 缓存相关的参数,例如:SHOW GLOBAL STATUS LIKE 'Innodb_buffer_pool_read_requests'。
  5. 当 InnoDB 缓存使用率达到 80% 时,就需要考虑适当调整 InnoDB 缓存的大小,以避免系统出现内存不足的情况。
  6. 一般来说,可以将 InnoDB 缓存设置为系统可用内存的 50% 到 70%。可以使用以下命令来设置 InnoDB 缓存的大小:SET GLOBAL innodb_buffer_pool_size = size。
  7. 在调整 InnoDB 缓存大小时,需要根据系统的实际情况进行调整,并在修改之前备份数据。另外,修改 InnoDB 缓存大小后,需要重启 MySQL 才能生效。
暂无回复。
需要 登录 后方可回复, 如果你还没有账号请点击这里 注册