RDS MySQL 见解:热门查询“commit”

Sim*_*non 8 mysql performance load commit amazon-rds

我们正在尝试通过性能洞察来减少 AWS RDS 实例上的负载。

洞察中列出的最上面的 SQL 语句是“commit”:

影响数据库负载的主要 sql 语句

特别是,commit 语句大部分时间都处于“init”状态:

等待提交语句的状态

当按状态查看总体负载时,这个“init”状态确实构成了负载的很大一部分:

按等待状态划分的总体数据库负载

因此,现在我们不太确定从这些信息中可以得到什么。

  1. 首先,我们启用了自动提交。此“COMMIT”语句是否包含自动提交配置中的自动 COMMIT 语句,还是仅在我们的应用程序执行事务时专用于显式 COMMIT 语句?
  2. 我检查了更多,似乎这个“init”状态与数据库将二进制日志刷新到磁盘有关(https://dev.mysql.com/doc/refman/8.0/en/general-thread-states.html)。这可能是有道理的,因为我们有sync_binlog=1我们的主人。但这个猜测是否正确,或者是否还涉及更多内容?
  3. 如果是这种情况,我阅读了有关调整sync_binlog(例如sync_binlog = 0或sync_binlog> 1)的信息,但在硬件故障的情况下风险更大(https://aws.amazon.com/blogs/database/best-practices- for-configuring-parameters-for-amazon-rds-for-mysql-part-2-parameters-related-to-replication/)。对于这一部分,我不清楚在使用一个主服务器和一些只读副本扩展 RDS 时什么是好的做法:在主服务器上进行此设置是标准做法,还是我们应该更多地关注减少我们正在处理的事务量从应用程序执行?
  4. 运行时我能够看到这些“COMMIT”语句停留在初始化状态SHOW FULL PROCESSLIST。但是,我想知道是否有一种方法可以查看与该 COMMIT 语句相关的查询。否则,似乎我们必须猜测什么交易是根本原因。

Sim*_*non 12

我们终于能够解决这个“提交”加载问题。

关于我们系统的一些事实:

  • 大约 95% 的 SQL 查询都是读取
  • 大约 5% 的写入查询是写入
  • 我们的大多数查询都是通过自动提交完成的,而不是通过显式事务完成

经过进一步调查,我们的发现如下:

  • 性能洞察中的“提交”负载来自将查询写入磁盘上的 binlog 所需的时间
  • 因为我们大多数写查询都是通过自动提交执行的,所以所有这些查询都会执行提交,从而触发一些 binlog 刷新
  • 读取查询不会增加此“提交”负载,很可能是因为它们不需要写入二进制日志
  • 因此,执行写入操作的 5% 的查询导致了大部分数据库负载!

对于我们来说,解决这个问题最有效的方法是在单个事务中批量写入。我们正在进行的许多写入不需要立即写入数据库,丢失其中一些可能是可以接受的(我们的大多数写入与统计或跟踪相关)。因此,我们当前的解决方案是将统计/跟踪写入存储到缓存中,并在单个事务中偶尔将它们刷新到数据库。这减少了提交次数,有效减少了负载。

该解决方案可能并不适合所有人,或者可能需要一些调整。根据我的理解,有一些替代解决方案,例如:

  • 对数据库进行分片并将导致大量写入负载的表移动到另一个实例
  • 减少写查询的数量
  • 使用二进制日志刷新设置。默认情况下,它会在每次 COMMIT 后将 binlog 刷新到磁盘,但可以进行不同的配置。但是,如果数据库崩溃,这可能会带来一些可恢复性问题!
  • 使用更快的磁盘

我也在下面回答了我原来的问题。

希望这对其他人有帮助。我发现网上与此相关的信息很少。

首先,我们启用了自动提交。此“COMMIT”语句是否包含自动提交配置中的自动 COMMIT 语句,还是仅在我们的应用程序执行事务时专用于显式 COMMIT 语句?

此“COMMIT”语句包括使用自动提交执行的查询。

此外,在我们的上下文中,此“COMMIT”语句中没有包含任何读取查询,很可能是因为读取查询后不需要将二进制日志刷新到磁盘。

我检查了更多,似乎这个“init”状态与数据库将二进制日志刷新到磁盘有关(https://dev.mysql.com/doc/refman/8.0/en/general-thread-states.html)。这是有道理的,因为我们的 master 上有sync_binlog=1。但这个猜测是否正确,或者是否还涉及更多内容?

对于我们来说,只有 binlog 刷新会导致此初始化状态期间的高负载。

如果是这种情况,我阅读了有关调整sync_binlog(例如sync_binlog = 0或sync_binlog> 1)的信息,但在硬件故障的情况下风险更大(https://aws.amazon.com/blogs/database/best-practices- for-configuring-parameters-for-amazon-rds-for-mysql-part-2-parameters-related-to-replication/)。对于这一部分,我不清楚在使用一个主服务器和一些只读副本扩展 RDS 时什么是好的做法:在主服务器上进行此设置是标准做法,还是我们应该更多地关注减少我们正在处理的事务量从应用程序执行?

标准做法是保留sync_binlog=1主服务器以避免崩溃后出现可恢复性问题,特别是在配置了只读副本的情况下。

还有其他方法可以解决这个问题,如我的回答中所列。

运行 SHOW FULL PROCESSLIST 时,我能够看到这些“COMMIT”语句停留在初始化状态。但是,我想知道是否有一种方法可以查看与该 COMMIT 语句相关的查询。否则,似乎我们必须猜测什么交易是根本原因。

正如此博客文章中所述,这是可行的: https: //www.psce.com/en/blog/2015/01/22/tracking-mysql-query-history-in-long-running-transactions/

但是,它需要启用 events_statements_history。据我所知,在 RDS 上,此功能被禁用,并且不允许启用它。

  • 太有帮助了!感谢您对问题各部分的详细分析和解释。 (2认同)