从 Percona Server for MySQL 5.6.27 开始的 information_schema.processlist 表的列 TID 将进程列表 ID 映射到操作系统线程 ID 的支持。随着 5.7 的发布,MySQL 通过扩展 PERFORMANCE_SCHEMA.THREADS 表并添加一个名为 THREAD_OS_ID 的新列来跟随其自己的实现,Percona Server for MySQL 采用该列代替自己的列,因为它通常会尽可能靠近上游.
以下方法对于查询使一个特定 CPU 过载而其他内核正常执行的情况很有用。对于一般 CPU 使用率问题的情况,可以使用不同的方法,例如另一篇博客文章 Reducing High CPU on MySQL: A Case Study 中的方法。
我们如何使用这个新列来找出哪个会话在我的数据库中使用了最多的 CPU 资源?
让我们举一个例子:
要解决 CPU 问题,我们可以使用多种工具,例如 top 或 pidstat(需要 sysstat 包)。在以下示例中,我们将使用 pidstat。该工具有一个选项 (-t),可将其视图从进程(默认)更改为线程,其中显示给定进程中的关联线程。我们可以使用它来找出服务器中消耗最多 CPU 的线程。将 -p 参数与 mysql 进程 id 一起添加,以便工具仅显示 MySQL 线程,以便我们更轻松地进行故障排除。最后一个参数(1)是每秒显示一个样本:
命令是 pidstat -t -p1:
我们可以看到线程 32053 以相当大的幅度消耗了最多的 CPU,并且我们确保在 pidstat 的多个样本中验证消耗是恒定的。使用该信息,我们可以登录数据库并使用以下查询找出哪个 MySQL 线程是罪魁祸首:
SE LECT * from performance_schema.threads where THREAD_OS_ID=查到的Tid\G
现在我们知道高 CPU 消耗来自 joinit 表中的查询,由用户 msandbox 在数据库测试中从 localhost 执行。使用此信息,我们可以对查询进行故障排除并使用 EXPLAIN 命令检查执行计划,以查看是否有任何改进空间。
explain se lect * from test.joinit where b='a a eveniet ut. '
在这种情况下,它是一个简单的索引丢失了!
创建索引后,我们不再看到 CPU 峰值:
为什么不使用这种方法来解决 IO 和内存问题?
从操作系统端测量线程 IO 的问题在于,大多数 MySQL IO 操作是由后台线程完成的,例如读取、写入和页面清理线程。要测量线程 IO,您可以使用带有 -d(IO 而不是 CPU)选项的 pidstat 或带有 -H(每个线程)的 iostat 等工具。如果您有一个非常消耗 IO 的线程,您可能能够看到它,但请注意,由于后台线程操作,结果可能会产生误导。
内存消耗是从操作系统端衡量的更棘手的资源,因为所有内存都是在 MySQL 进程下分配的,并且由于是 MySQL 管理其内存访问,因此对于操作系统来说哪个线程消耗最多内存是透明的。为此,我们可以使用从 5.7 开始可用的 perfomance_schema 内存检测。
结论
有许多方法可以解决 CPU 使用率过高的问题,但这里我们介绍了一种简单的、广泛使用的方法,适用于 Oracle 和 PostgreSQL 数据库,从版本 5.7 开始,可以适应 MySQL。通过从操作系统线程消耗跟踪到数据库端,我们可以快速检测影响系统性能的 CPU 密集型查询。
正确理解数据库性能问题的真正原因可以快速有效地解决问题——但企业往往缺乏这种关键信息。没有它,您的解决方案可能需要比必要更多的时间和资源,或者无法有效地解决问题。与流行的看法相反,问题并不总是数据库本身!
总结:
1)pidstat -t -p1:找出CPU高的THREAD_OS_ID;
2) 可知THREAD_OS_ID查找到SQL文本;
|