【问题标题】:AWS RDS MySQL performance drop after random timespan随机时间跨度后 AWS RDS MySQL 性能下降
【发布时间】:2017-05-04 06:59:30
【问题描述】:

问题大纲 我们的 AWS RDS 实例在大约 7 到 14 天后开始减速,速度下降幅度很大(特定查询集的加载时间约为 400%)。 RDS 监控没有显示资源短缺的迹象。 (详细问题描述见下方问题更新)


问题更新

因此,经过一个多月的调查和 AWS 的一些开发人员支持,我并没有完全接近解决方案。

以下是我从列表中核对的几个步骤,或多或少没有任何进一步的问题提示:

  • 索引/碎片(所有表都有正确的索引/键并且没有碎片)
  • MySQL 统计更新(手动更新统计source
  • 线程并发(将 innodb_thread_concurrency 更改为各种不同的参数)
  • 查询缓存命中率不显示问题
  • 解释看看是否有任何 SELECT 真的很慢或没有使用索引/键
  • SLOW QUERY LOG(不返回任何结果,因为请参阅下面的段落,这是一些准备好的 SELECT)
  • RDS 和 EC2 在一个 VPC 中

为了解释,使用的 PlayFramework (2.3.8) 有 BoneCP,我们正在使用 eBeans 来选择我们的数据。所以基本上我正在运行一个嵌套对象和所有这些子对象,这会为相关 API 调用生成数百个准备好的 SELECT。对于使用的硬件,这基本上也应该没问题,这些操作都没有广泛使用 CPU 和 RAM。

我还加入了 NewRelic,以获取有关此问题的更多见解,并进行了一些 JVM 分析。显然,大部分时间都被 NETTY/eBeans 消耗了?

有人能理解这个吗?


原始问题:问题大纲

我们的 AWS RDS 实例在大约 7-14 天后开始变慢,速度变慢了相当大的因素(特定查询集的加载时间约为 400%)。 RDS 监控没有显示资源短缺的迹象。

基础设施

我们为 AWS EC2 实例上的移动应用程序运行 PlayFramework 后端,连接到 AWS RDS MySQL 实例、一个 PROD 环境、一个 DEV 环境。通常 PROD EC2 实例指向 PROD RDS 实例,而 DEV EC2 指向 DEV RDS(很明显,队长您好!);但是有时我们也让 DEV EC2 指向 PROD DB 以用于某些测试目的。正在使用的 PlayFramework 与 BoneCP 一起使用。

详细问题描述

在一个非常重要的同步过程中,我们的应用每天都会对每个用户多次调用某个 API。我在this SO question 中讨论了该功能的背景,感谢 cmets,我可以将问题归结为某种 MySQL 问题。

简而言之,API调用是加载一组数据,最大约1MB的json数据,目前加载大约需要18s。当一切运行良好时,加载大约需要 4 秒。

很好奇,上次“解决”问题的是将 RDS 实例升级到另一种实例类型(从 db.m3.large 到 db.m4.large,这只是一个非常边缘的步骤)。现在,大约 2-3 周后,RDS 实例再次像以前一样缓慢运行。重启 RDS 实例没有任何效果。重新启动 EC2 实例也没有任何效果。

我还检查了受影响的 mySQL 表的索引是否设置正确,情况确实如此。 API 调用本身不会急切加载任何 BLOB 字段或类似字段,我对此进行了仔细检查。 RDS 实例的 CPU 使用率大部分时间都低于 1%,当我用 100 个并发 API 调用对其进行压力测试时,它达到了 ~5%,所以这不是瓶颈。内存也很好,所以我猜 RDS 实例不会开始交换,这可能会减慢整个过程。

提供确凿的证据,在 DEV 环境中(较小的)公共 API 调用当前需要 2.30 秒的负载,在 PROD 环境中需要 4.86 秒。这很有趣,因为 DEV 环境在 EC2 和 RDS 中都有一个小得多的实例类型。所以基本上乌龟在这里赢得了比赛。 (如果您对此 API 调用感兴趣,我很乐意通过 PN 与您分享,但我真的不想发布 API 调用的链接,即使它们基本上是公开的。)

结论

最后,感觉(我故意说“感觉”)数据库在使用 x 天后/在一定数量的 API 调用后被阻塞。不确定这是否是特定于 RDS 的问题,一旦我通过更改实例类型“很大程度上”重置数据库实例,事情就会运行得又快又顺利。但是每 2 周从快照重新创建我的数据库实例不是一种选择,特别是如果我不明白为什么会发生这种情况。

您知道我可以采取哪些进一步措施来调查此事?

【问题讨论】:

  • 仅加载 1MB 数据的 API 调用应该比您遇到的要快得多。您的问题没有显示任何事实结论表明这是 MySQL 的错,这意味着您可能正在查看症状而不是原因。您是否测量了您的 RDS 实例的I/O?您的数据集大小是多少?您的 innodb_buffer_pool_size 值是多少?你很少会遇到 MySQL 的 CPU 瓶颈,通常是 I/O 子系统阻塞了性能。
  • 好吧,数据分布在一些表上并连接起来,因此通过 1 次 API 调用会触发许多准备好的语句。所以计算确实需要一些时间。事实结论在前面提出的 SO 问题中陈述,我起初错误地得出结论,JSON(反)序列化是罪魁祸首。实验破坏了它,如果我将相同的代码从 PROD RDS 实例切换到 DEV RDS 实例,消耗的时间会减少(尽管 PROD 有更多资源)。 (转到下一条评论,字符用完了.. ;))
  • 我还没有测量RDS实例的I/O,但是为什么一段时间后会减少呢?特别是,PROD 环境比 DEV 环境具有更强的规格。有问题的数据库的数据集大小约为 800MB,innodb_buffer_pool_size 由 RDS 设置为可用 RAM 的 75%(在我的情况下是 6123683840)。我完全同意 CPU 不是瓶颈。
  • 我可以告诉你我的猜测,但准确地确定总比相信一些随机人的猜测要好:) 这可能是你创建了太多文件描述符的情况。但是,我从未见过它影响 MySQL 的程度。您是否尝试过使用 MySQL 的慢查询日志功能来确定哪些查询很慢?您知道每秒要处理多少个查询以及您的服务器可以提供多少?您是否使用innodb_file_per_table,如果是 - 有多少张桌子?你使用持久的数据库连接吗?
  • 如果我是你,我会尝试使用慢日志。如果与 MySQL 交谈花费了这么多时间,那么慢查询日志会告诉你它是什么。它可能是这几百个查询中的大部分,也可能是其中之一——重点是,该日志会告诉你到底发生了什么。您是否在事务中准备和执行准备好的语句?这非常重要,因为这决定了 MySQL 如何使用其 I/O。我有一种预感,如果事实证明 MySQL 是问题所在,那么您会受到 I/O 限制。 EXPLAIN EXTENDED 还可以告诉您查询的哪一部分速度较慢 - 查找、解析或通过网络发送。

标签: mysql database amazon-web-services netty amazon-rds


【解决方案1】:

(评论太长了)我知道你已经检查了很多东西,但我想用不同的眼光来看待它们......

请提供

SHOW VARIABLES;  (probably need post.it or something, due to size)
SHOW GLOBAL STATUS;
how much RAM?  Sounds like 7.5G
The query.  -- Unclear what query/queries you are using
SHOW CREATE TABLE  for the table(s) in the query -- indexes, datatypes, etc

(以上一些可能有助于解决“随着时间的推移堵塞”的问题。)

同时,这里有一些猜测/问题/等等......

  • 共享硬件的其他客户正忙。
  • 可能是网络问题?
  • long_query_time 缩小为 1,这样您就可以捕获慢查询。
  • 什么时候在您的实例上完成备份?
  • 4s-18s 加载一兆字节 -- 其中有多少百分比是 SQL 语句?
  • 您是否“批量”插入?是单笔交易吗?是否同时进行冗长的查询?
  • 您从 AWS 默认值更改了哪些 MySQL 可调参数(如果有)?
  • 7.5GB 分区上的 6GB 缓冲池?这听起来很危险。你能看看有没有交换吗?
  • 任何PARTITIONing 参与? (当然CREATE 会回答这个问题。)

【讨论】:

  • 谢谢!广告显示变量/全局状态:我应该查看任何特定值吗? (s3.eu-central-1.amazonaws.com/mmg-standard/assets/misc/…s3.eu-central-1.amazonaws.com/mmg-standard/assets/misc/… 用于 .txt 中的输出)。内存为 8GB。查询来自 eBean(我正在选择一组嵌套对象),还有一些改进的空间 - 但基本上它可以正常工作。索引/键很好。对于您的其他观点:没有其他客户使用硬件...(续下一条评论)
  • ... 网络应该没问题(得到 AWS 支持团队的保证)。 long_query 在这里对我没有帮助(很多短选择而不是 1 个慢查询)。每周进行一次备份(RDS 默认)。 SQL 的百分比约为
  • 变量/状态中没有太多令人兴奋的值。 max_allowed_packet 高达 1GB,非常危险。 15 qps 低;各种与 IO 相关的指标反映了这一点。 Max_used_connections = 40 表示您的活动量显着增加;或者什么东西挂了很长一段时间。慢查询和表扫描很高,但系统不是很忙。每 5 分钟进行一次吹扫和冲洗;为什么?我查看了 120 个计算变量/状态/表达式。
  • 感谢您@Rick James 的努力! max_allowed_packet 很高,因为我们的表中曾经有(大!)BLOB。我将其重新安排为存储在 S3 存储桶中,因此我完全可以将其调低。 max_used_connections - 嗯,这个值与 BoneCP 以一种(对我来说)不完全明显的方式联系在一起。因此,当我们的应用程序工作时,这是 5-15 个连接,当两个环境都连接到 RDS 实例时,这加起来。最后,当我重新启动/更新一个 EC2 实例时,这一次可能是 3 个实例,这可以解释 ~40. (这些是我的假设!)
  • OK -- 将max_allowed_packet 保持在高位,但通过降低innodb_buffer_pool_size 为其腾出空间。你确实不想想要交换;这对性能来说是很糟糕的。也许交换时发生了40。流程会开始,但需要永远完成。
【解决方案2】:

您的描述中缺少一个非常重要的信息:为数据库分配的总空间。 RDS 的 I/O 大约是分配空间的 3 倍,因此对于 100GB 的分配,您应该获得大约 300 IOPS。分配的空间还包括日志。

由于您并不真正知道发生了什么,所以第一步应该是打开详细监控,这将使您对实例上发生的事情有更多的了解。

在减速期间收集到额外的统计数据之前,您可以尝试增加分配的空间,这将增加可用的 IOPS。

另外,检查数据库的事件 - 是否定期清除日志?这可能表明空间不足。

最后,如果您知道应用程序需要什么,您可以尝试使用 PIOPS(预置 IOPS),尽管此时这听起来像是一个猜测。

【讨论】:

  • 我分配了 100 GB 的存储空间,但现在我将其设置为 GENERAL PURPOSE 而不是预置的 IOPS。这可能是一个问题吗? 100 GB 是相当大的,我摆脱了我们数据库中所有遗留的 BLOB 表,所以基本上 2 GB 的存储空间对于这个数据库来说已经绰绰有余了。我同意在减速期间我需要更多数据,我已经设置了 NewRelic 并尝试在此时尽可能多地收集。感谢您的评论!
  • @konrad_pe:您将从 RDS 详细统计数据中获得比 New Relic 所能提供的更多信息。
  • 好的,刚刚开启了RDS实例的详细监控。
【解决方案3】:

也许您的突发信用余额正在(缓慢地)耗尽?最后,您最终会获得基线性能,这可能看起来“太慢”。

这也可以解释为什么升级到另一种实例类型确实有帮助,因为您随后又开始使用完全突增的余额。

我建议增加卷的大小,即使您不需要额外的空间,as the baseline performance grows linearly with volume size

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2016-05-16
    • 1970-01-01
    • 2018-08-20
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-01-22
    • 1970-01-01
    相关资源
    最近更新 更多