3

I run a website with ~500 real time visitors, ~50k daily visitors and ~1,3million total users. I host my server on AWS, where I use several instances of different kind. When I started the website the different instances cost rougly the same. When the website started to gain users the RDS instance (MySQL DB) CPU constantly keept hitting the roof, I had to upgrade it several times, now it have started to take up the main part of the performance and monthly cost (around 95% of (2,8k$/month)). I currently use a database server with 16vCPU and 64GiB of RAM, I also use Multi-AZ Deployment to protect against failures. I wonder if it is normal for the database to be that expensive, or if I have done something terribly wrong?

Current settings

enter image description here

Database Info

At the moment my database have 40 tables with the most of them have 100k rows, some have ~2millions and 1 have 30 millions. I have a system the archives rows that are older then 21 days when they are not needed anymore.

Website Info

The website mainly use PHP, but also some NodeJS and python.

Most of the functions of the website works like this:

  1. Start transaction
  2. Insert row
  3. Get last inserted id (lastrowid)
  4. Do some calculations
  5. Updated the inserted row
  6. Update the user
  7. Commit transaction

I also run around 100bots wich polls from the database with 10-30sec interval, they also inserts/updates the database sometimes.

Extra

I have done several things to try to lower the load on the database. Such as enable database cache, use a redis cache for some queries, tried to remove very slow queries, tried to upgrade the storage type to "Provisioned IOPS SSD". But nothing seems to help.

This is the changes I have done to the setting paramters:

enter image description here

I have though about creating a MySQL cluster of several smaller instances, but I don't know if this would help, and I also don't know if this works good with transactions.

If you need any more information, please ask, any help on this issue is greatly appriciated!

4

3 回答 3

6

根据我的经验,一旦您提出“我如何才能提高性能?”的问题。你知道你已经超越了 RDS(编辑:我承认我的经验导致我这个观点可能已经过时了)。

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

我还将禁用 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 秒的查询,但它们运行如此频繁以至于对服务器造成负担。

在您知道哪些查询占负载后,您可以制定一些有关如何解决它们的明智策略:

  • 查询优化或重新设计
  • 应用程序中的更多缓存
  • 横向扩展至更多实例
于 2016-07-10T15:43:08.150 回答
2

Aquery_cache_size超过 50M 是个坏消息。你经常写——每张桌子每秒写很多次?这意味着需要每秒多次扫描 QC 以清除已更改表的条目。当 QC 为 2.5GB 时,这对系统来说是一个很大的负载!

query_cache_type应该是DEMAND,如果你能证明它的存在是合理的。SELECTs在这种情况下,用SQL_CACHEand胡椒粉SQL_NO_CACHE

由于您已打开慢速日志,因此请使用 pt-query-digest 查看输出。前几个查询是什么?

由于您的典型操作涉及写入,因此我看不到使用只读从属设备的优势。

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

您如何“归档”“旧”记录?最好使用PARTITIONing“可传输表空间”。使用PARTITION BY RANGE和 21 个分区(加上一些额外的)。

您的典型事务似乎与一行一起工作。可以修改它以同时使用 10 或 100 吗?(超过 100 条可能不符合成本效益。)SQL 在一次执行大量行方面比在一行中执行大量查询要高效得多。向我们展示 SQL;我们可以深入了解细节。

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

“用户”是否相互交互?如果真是这样,那么是以哪种方式?

于 2016-07-10T22:39:53.003 回答
2

我认为答案是“你做错了什么”。您不太可能达到 RDS 限制,尽管您可能会在其中的某些部分达到限制。

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

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

您也可以迁移到 Aurora,这应该会为您提供更好的 I/O 性能。或使用 PIOPS(或分配更多磁盘,这应该会提高性能)。您使用的是 SSD 存储,对吗?

另一个建议 - 如果您的计算(上面的第 4 步)需要大量时间,您可能希望将其分解为两个或多个事务。

于 2016-07-10T20:06:20.863 回答