写点什么

是什么引起数据库响应超时?

作者:BUG侦探
  • 2022 年 9 月 20 日
    北京
  • 本文字数:1853 字

    阅读完需:约 6 分钟

是什么引起数据库响应超时?

一、问题背景

一个核心业务数据库部署在 AWS 的 EC2 实例上,在业务活动期间发生了性能抖动导致业务超时。

下面记录一下问题排查的流程。

二、问题分析

1. 监控指标分析

发生问题后,第一时间肯定要看监控!首先分析服务器基础监控。

服务器的 Load1 使用率不足 40%,看上去未达到瓶颈。

​发现问题发生期间,数据盘的 IOPS 有不规律的波动,但是整体上 IOPS 峰值未超过 1500,看上去不像达到了瓶颈。

​再观察一下 MySQL 服务指标,可以看到问题发生时数据库运行线程是有突增的,同时也观察到数据库 insert 和 update 同样有突增。

这一点与调用方确认当时确实是有大量的写入和更新,但是从服务指标上看并没有达到服务运行的瓶颈。

​2. 漫长的排查流程

重新梳理一下各方的情况。

基础监控

我们又重新 Review 了服务器监控指标,确认当时服务器的 CPU 使用率、内存使用率、磁盘使用率和磁盘 IOPS 均没有达到上限,基础资源部分看起来正常。

MySQL 服务

MySQL 层面没有慢查询日志,说明 MySQL 本身的处理逻辑正常,业务也并没有新增不合理的 SQL。只是发现当时 MySQL 的 threads_running 有上涨,说明当时排队的请求很多,具体为啥就不知道了。

业务调用方

业务当时没有上线或其它变更。从调用量上来看,是有突增的,这也与 MySQL 的监控指标吻合。

但是业务本身的资源使用率正常,处理其它逻辑的耗时也正常,只是对 MySQL 请求慢了,因此不像是业务本身的问题导致。

看了一圈只是看出当时 MySQL 慢了,但是为啥慢了还是不清楚,问题究竟出在哪里?

3. 被忽略的指标

想来想去,影响 MySQL 最重要的还是两类资源:CPU 和磁盘 IO。

CPU 使用率从监控上看基本没有大的波动,但是磁盘 IO 确实是有明显波动的,只是没有达到 IOPS 的阈值。所以磁盘 IO 还是重点怀疑对象

从监控大盘上看 IOPS 峰值不超过 1500,看似未达到瓶颈,但监控采点间隔是 1 分钟,会不会有瞬时突增达到了上限但是监控没有采集到(实际该磁盘 IOPS 配置上限为 6000)?

关于这点我们咨询了 AWS 后台工程师,AWS 的 EBS 存在一个我们之前忽略的监控指标:VolumeIdleTime。官方对这个指标的描述如下:

VolumeIdleTime – The amount of time when no read or write operations were waiting to be completed during the period.意思是 EBS 实例在监控周期内没有读写操作的时间。

那么我们查看一下发生问题的 EBS 实例这个指标的情况:

结果令人吃惊,该实例每分钟的空闲时间超过 50s,按这个计算,实际峰值的 IOPS 可能是监控指标的 6 倍!1500 * 6 = 9000,很显然已经超出了 EBS 配置的 IOPS 限额 6000!

我们可以在 CloudWatch 上配置一个自定义指标:(每分钟读 IO 次数+每分钟写 IO 次数)/(1 分钟-VolumeIdleTime),来更直观的观察 EBS 实例实际 IOPS 的波动情况。

通过下图可以看到,确实有很多突增的点 IOPS 峰值超过了 6000,这是导致 MySQL 访问超时的直接原因。

​至此,问题根因得到了确认。

三、总结

我们最后总结一下问题原因:

  1. 业务写入突增导致 MySQL 服务对应的底层 EBS 实例 IOPS 飙升,短时间超出限额 6000 导致性能受限,引起业务超时;

  2. EBS 实际的 IOPS 可以通过 VolumeIdleTime 指标做更精确的计算。

四、后续优化方向

1. 如何快速查看 EBS 实例真实的 IOPS

这个指标由 3 个 CloudWatch 原始指标聚合而成,配置较为繁琐。

我们可以提前保存一个 CloudWatch 源指标模板:

{    "metrics": [        [ { "expression": "(m1+m2)/(PERIOD(m1)-m3)", "label": "Actual IOPS", "id": "e1" } ],        [ "AWS/EBS", "VolumeReadOps", "VolumeId", "your_volume_id", { "id": "m1", "visible": false } ],        [ ".", "VolumeWriteOps", ".", ".", { "id": "m2", "visible": false } ],        [ ".", "VolumeIdleTime", ".", ".", { "id": "m3", "visible": false } ]    ],    "view": "timeSeries",    "stacked": false,    "region": "ap-southeast-1",    "stat": "Average",    "period": 60}

复制代码

需要查看时只需要替换一下 VolumeId 和 region 即可查看对应 EBS 实例的自定义 Actual IOPS 指标。

2. 增加秒级监控

排查问题时,我们永远都希望监控的粒度越细越好,但是更频繁的指标采集动作可能会导致服务器本身的压力上升。因此在增加秒级监控指标时需要谨慎的评估这一点。

我们可以只选择最关注的核心指标,将少量的指标增加秒级监控,这样在尽量不增加服务器压力的同时达到细粒度指标采集的目的。

3. 推动业务优化

由于 EBS 的性能普遍比机房物理机上的 SSD 性能要差,业务需要更严格的判断突增请求的合理性,是否能通过消息队列进行削峰填谷,使请求更加平稳。

同时为缓解业务异常,可以使用 GP3 类型 EBS 实例,把 IOPS 配额临时调大,等业务优化后再将 IOPS 配额恢复。







发布于: 刚刚阅读数: 5
用户头像

BUG侦探

关注

还未添加个人签名 2021.06.08 加入

专注于发掘程序员/工程师的有趣灵魂,对工作中的思路与总结进行闪光播报。

评论

发布
暂无评论
是什么引起数据库响应超时?_MySQL_BUG侦探_InfoQ写作社区