MySQL服务器负载很高

时间:2016-07-10 15:06:13

标签: mysql database performance amazon-web-services aws-rds

我运营的网站包含 ~500名实时访问者 ~50k每日访问者 ~1,300万总用户。我在 AWS 上托管我的服务器,在那里我使用了不同类型的多个实例。当我启动网站时,不同的实例成本相同。当网站开始获得用户时,RDS实例(MySQL DB)CPU不断地进入屋顶,我不得不多次升级,现在它已经开始占用主要部分的性能和每月成本(约95%的(2,8k $ /月))。我目前使用的是具有16vCPU和64GiB RAM的数据库服务器,我还使用多可用区部署来防止故障。 我想知道数据库的价格是否正常,或者我做错了什么?

Current settings

enter image description here

数据库信息

目前我的数据库有40个表,其中大多数表有100k行,有些表有~2百万,1表有3千万。 我有一个系统档案行,这些行在21天之后不再需要了。

网站信息

该网站主要使用PHP,还有一些NodeJS和python。

网站的大部分功能都是这样的:

  1. 开始交易
  2. 插入行
  3. 获取最后插入的ID(lastrowid)
  4. 做一些计算
  5. 更新了插入的行
  6. 更新用户
  7. 提交交易
  8. 我还会以10-30秒的间隔从数据库中运行100个左右的轮询,它们有时会插入/更新数据库。

    附加

    我已经做了几件事来尝试降低数据库的负载。如启用数据库缓存,对某些查询使用redis缓存,尝试删除非常慢的查询,尝试将存储类型升级为“Provisioned IOPS SSD”。但似乎没有任何帮助。

    这是我对设置参数所做的更改:

    enter image description here

    我有关于创建一个包含几个较小实例的MySQL集群,但我不知道这是否会有所帮助,而且我也不知道这是否适用于事务。

    如果您需要更多信息,请询问,对此问题的任何帮助都非常有用!

3 个答案:

答案 0 :(得分:5)

根据我的经验,一旦你提出问题"我怎样才能扩大表现?"你知道你已经超出了RDS(编辑:我承认我的经历导致我的观点可能已经过时)。

听起来你的查询负载非常重要。大量的插入和更新。如果可以使用您的RDS版本,则应增加innodb_log_file_size。否则,您可能不得不放弃RDS并转移到EC2实例,您可以更轻松地调整MySQL。

我还会禁用MySQL查询缓存。在每次插入/更新时,MySQL都必须扫描查询缓存,以查看是否有任何需要清除的缓存结果。如果您的工作量很大,那就浪费时间了。将查询缓存增加到2.56GB会使情况变得更糟!将缓存大小设置为0,缓存类型设置为0.

我不知道您运行的是什么查询,或者您对它们的优化程度。 MySQL的优化器是有限的,因此通常情况下,您可以从重新设计SQL查询中获得巨大的好处。也就是说,更改查询语法,以及添加正确的索引。

您应该进行查询审核,以找出哪些查询会导致您的高负载。一个很好的免费工具是https://www.percona.com/doc/percona-toolkit/2.2/pt-query-digest.html,它可以根据您的慢查询日志为您提供报告。使用http://docs.aws.amazon.com/cli/latest/reference/rds/download-db-log-file-portion.html CLI命令下载RDS慢查询日志。

设置你的long_query_time = 0,让它运行一段时间来收集信息,然后将long_query_time改回你通常使用的值。收集此日志中的所有查询非常重要,因为您可能会发现75%的负载来自2秒以内的查询,但它们的运行频繁,以至于它对服务器造成负担。

在您知道哪些查询考虑了负载后,您可以制定一些有关如何解决这些问题的明智策略:

  • 查询优化或重新设计
  • 应用程序中的更多缓存
  • 扩展到更多实例

答案 1 :(得分:2)

我认为答案是"你做错了什么"。你不太可能达到RDS限制,尽管你可能会对它的某些部分施加限制。

首先启用详细监控。这将为您提供一些操作系统级别的信息,这些信息有助于确定您的限制因素究竟是什么。查看慢速查询日志和数据库统计信息 - 您可能会遇到一些导致问题的查询。

一旦你理解了问题 - 可能是错误的查询,I / O限制或其他 - 那么你就可以解决它们。 RDS允许您创建多个只读副本,因此您可以将一些读取负载移动到从属。

你也可以转移到Aurora,这应该会给你更好的I / O性能。或者使用PIOPS(或分配更多磁盘,这应该可以提高性能)。你正在使用SSD存储,对吗?

另一个建议 - 如果您的计算(上面的步骤4)需要花费大量时间,您可能需要将其分解为两个或更多交易。

答案 2 :(得分:2)

超过50万的query_cache_size是坏消息。你经常写作 - 每张桌子每秒多次?这意味着需要多次扫描QC以清除更改的表的条目。当质量控制为2.5GB时,这对系统来说是一个很大的负担!

query_cache_type应该是DEMAND,如果你可以证明它完全正确的话。在这种情况下,请SELECTsSQL_CACHESQL_NO_CACHE

由于您打开了slowlog,请使用pt-query-digest查看输出。第一对查询是什么?

由于您的典型操作涉及写作,因此我没有看到使用只读Slaves的优势。

机器人是否随机运行?或者它们都是同时开始的? (后者可能会导致CPU等出现可怕的峰值)。

你是如何"归档" "旧"记录?最好使用PARTITIONing和"可传输表空间"。使用PARTITION BY RANGE和21个分区(以及一些额外内容)。

您的典型交易似乎只能使用一行。是否可以修改为一次使用10或100? (超过100个可能不具有成本效益。)SQL在一次执行大量行时效率更高,而每行查询很多。向我们展示SQL;我们可以深入了解细节。

在一个事务中插入一个新行然后更新它似乎很奇怪。在插入之前你不能完全计算它吗?长时间挂在inserted_id上可能会干扰其他人做同样的事情。 innodb_autoinc_lock_mode的价值是什么?

"用户"彼此互动?如果是这样,以什么方式?