【发布时间】: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