首页 > 解决方案 > 高 MySQL CPU 使用率 (300-400%)

问题描述

最近几天我的 MySQL CPU 使用率有问题,我的 CPU 使用率平均为 300%。MySQL 版本是 5.7,数据库有 ~150MB 非常感谢您的帮助。

服务器规格:

Intel(R) Xeon(R) CPU E3-1225 V2 @ 3.20GHz
16GB DDR3

从 mysqladmin 登录

Uptime: 271  Threads: 6  Questions: 202964  Slow queries: 0  Opens: 311  
Flush tables: 1  Open tables: 254  Queries per second avg: 748.944

我的.cnf

[mysqld_safe]
socket          = /var/run/mysqld/mysqld.sock
nice            = 0

[mysqld]
user            = mysql
pid-file        = /var/run/mysqld/mysqld.pid
socket          = /var/run/mysqld/mysqld.sock
port            = 3306
basedir         = /usr
datadir         = /var/lib/mysql
tmpdir          = /tmp
lc-messages-dir = /usr/share/mysql
skip-external-locking

sql_mode = STRICT_TRANS_TABLES,NO_ZERO_IN_DATE,NO_ZERO_DATE,ERROR_FOR_DIVISION_BY_ZERO,NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION

bind-address            = 127.0.0.1

key_buffer_size         = 16M
max_allowed_packet      = 16M
thread_stack            = 192K
thread_cache_size       = 8
myisam-recover-options  = BACKUP
max_connections        = 2000

query_cache_limit       = 1M
query_cache_size        = 16M

log_error = /var/log/mysql/error.log

expire_logs_days        = 10
max_binlog_size   = 100M
query_cache_type=ON
query_cache_size=256M

innodb_buffer_pool_size=12G
innodb_log_buffer_size=128M
innodb_write_io_threads = 4
innodb_read_io_threads  = 4

mysqltuner 日志 https://pastebin.com/raw/xv4FPjpe

findfragtables.sql 日志 https://pastebin.com/raw/TGP5qjtV

ulimit -a https://pastebin.com/raw/AeYKtqHH

显示引擎 INNODB 状态 https://pastebin.com/raw/bEZG5GEc

显示全球状态 (30.10.2018 12:28 UTC+2) https://pastebin.com/raw/1zFsTYNf

USER       PID %CPU %MEM    VSZ   RSS TTY      STAT START   TIME COMMAND
mysql    15632  277  8.8 16271348 1447256 ?    Sl   13:58 169:28 /usr/sbin/mysqld --daemonize --pid-file=/var/run/mysqld/mysqld.pid

标签: mysql

解决方案


当您的整个数据集适合缓冲池时,就无需等待 I/O,这通常是瓶颈,因为它比 RAM 慢得多。

因此,如果您对已经在 RAM(缓冲池)中的数据运行大量只读查询,那么限制资源就是 CPU,因为它会扫描和搜索 RAM 中的数据。这就是为什么您的 CPU 负载看起来如此之高的原因。它只是稳定地忙于工作,因为它不需要等待其他任何事情。

证据在“BUFFER POOL AND MEMORY”下处于 InnoDB 状态:

页面读取 7814,创建 70,写入 3805 7.32 读取/秒,0.00 创建/秒,3.55 写入/秒缓冲池命中率 1000 / 1000,年轻化率 0 / 1000 不是 0 / 1000

“created”统计数据是第一次必须加载到缓冲池中的页面数。它是如此之低,因为实际上所有页面都已经在缓冲池中。

“命中率”是查询请求页面并且它已经在缓冲池中的次数,因此无需再次从磁盘加载它。这是1000/1000,表示每次请求一个页面时,它已经被加载了。或者至少 99.9% 的时间。

按照建议调整缓冲池的大小后,您可能会重新启动 MySQL 服务器,这将驱逐缓冲池的内容。重新启动后,您的查询将从磁盘读取页面以将它们恢复到缓冲池,因此它们必须等待 I/O。但最终你会再次达到所有数据都在缓冲池中的地步,我预测你会看到 CPU 负载再次增加。

我还注意到在您的 InnoDB 状态“行操作”中:

0.05 次插入/秒、0.50 次更新/秒、0.00 次删除/秒、4970813.64 次读取/秒

还有每秒的查询率:

每秒平均查询数:748.944

这意味着每秒大约 750 个查询负责每秒读取近 500 万行。每个查询平均超过 6,600 行。那是

我怀疑这是您的高 CPU 负载的根本原因。您的查询平均扫描很多页面,即使这些页面在 RAM 中。

鉴于您的整个数据库只有约 150MB,这非常令人惊讶。

您应该分析每个频繁运行的查询,以确定是否有一些索引可以帮助缩小搜索范围,这样您就不必在每个查询中检查如此多的行数。

您可能会喜欢我的演示如何设计索引,真的,或者我演示它的视频:https ://www.youtube.com/watch?v=ELR7-RdU9XU


推荐阅读