MySQL 8.0 trx_sys_mutex等待时间峰值

问题描述

在我们的网站发生故障期间,我们在MySQL慢速查询日志中观察到许多SQL的Lock_time:> 100秒 Lock_time较长的查询很简单(从慢速查询日志中复制以下内容)

SET timestamp=1599242815;
select `user`.`first_name`,`user`.`last_name`,`user`.`email` from `user` where `user`.`user_id` = <>;
# Time: 2020-09-04T18:13:12.674309Z
# User@Host: <>[<>] @  [<>]  Id: 2128691
# Query_time: 359.872340  Lock_time: 223.442795 Rows_sent: 1  Rows_examined: 1

user_id是此表的自动生成的主键(无符号int)。在慢查询日志中发现的所有其他SQL相似(通过PrimaryKey直接访问)

在慢速查询日志中找到的查询是随机的(不特定于特定的表组)。目前没有其他长期运行的高行扫描查询,尤其是没有长期运行的写事务。

以下是我们在performance_insights中发现的内容

trx_sys_mutex wait time spike

我们如何找出为什么对trx_sys_mutex的等待突然增加的原因?在手术的最后五年中,我们从未见过这种行为。

AWS RDS上的MySQL 8.0.19:32核计算机,对表使用innodb引擎。图片中显示的时间是在IST中,RDS自动备份窗口是事件发生时间之前的10小时

解决方法

除非您使用事务隔离级别SERIALIZABLE,否则SELECT查询不需要任何行锁。因此,它只能是元数据锁。每个查询都需要一个元数据锁,而其他任何持有该元数据锁的会话都可以阻止该查询。例如,任何ALTER / DROP / TRUNCATE / RENAME TABLE语句或LOCK TABLES。

我还看到Query_time是6分钟(359.87秒),其中超过两分钟是在完成锁定等待之后。

我假设user.user_id是该表的主键?因此,它通过主键查找了一行并且花了分钟来完成?花这么长时间是不现实的。

根据我的经验,只有在主机无响应时才会发生这种情况。它与您的SQL查询无关。

我会考虑其他可能性:

  • 一个嘈杂的邻居问题。也就是说,同一主机上的另一个RDS容器执行了某些操作,导致系统负载激增。不幸的是,AWS与属于不同账户的容器共享主机,因此这种事情可能发生,而且您永远都不知道是谁负责。

  • 主机上发生了任何与RDS容器无关的事情。也许是操作系统升级或故障转移之类的。同样,这将超出您的控制范围,您将无法进行检查。

您可以再次运行相同的查询,在相同的RDS实例上搜索相同的表以获取相同的值,并且花费很少的时间吗?那将指出主机上的暂时性问题,而不是您的查询问题。

正如我所说,任何查询都需要元数据锁定。必须获取此锁,这意味着存在非零数量的代码来检查是否存在不阻止查询的元数据锁。通常,这是如此之快,以至于您永远不会注意到它,但是如果主机超载,以至于正常操作需要花费几分钟,即使对元数据锁定的这种快速检查也可能会延长。

相关问答

依赖报错 idea导入项目后依赖报错,解决方案:https://blog....
错误1:代码生成器依赖和mybatis依赖冲突 启动项目时报错如下...
错误1:gradle项目控制台输出为乱码 # 解决方案:https://bl...
错误还原:在查询的过程中,传入的workType为0时,该条件不起...
报错如下,gcc版本太低 ^ server.c:5346:31: 错误:‘struct...