一、紧急定位:找出消耗cpu的mysql线程
首先要快速找到是哪些sql或连接在消耗cpu,这一步能帮你快速锁定问题。
1. 登录mysql,查看当前运行的线程
-- 查看所有活跃线程,按cpu使用时间排序(最耗cpu的排在前面)
show full processlist;
-- 更详细的查询(推荐),包含执行时间、锁等待等关键信息
select
id,
user,
host,
db,
command,
time,
state,
left(info, 500) as sql_text, -- 显示sql语句前500个字符
execution_time,
lock_time
from information_schema.processlist
where command != 'sleep' -- 排除休眠连接
and info is not null -- 排除无sql的线程
order by time desc; -- 按执行时间降序
关键字段解读:
time:sql执行的秒数(长时间运行的sql优先排查)state:线程状态(如sending data、sorting result、updating等,代表sql执行阶段)sql_text:具体执行的sql语句(核心排查对象)
2. 查看mysql全局状态和cpu相关指标
-- 查看mysql自启动以来的统计信息(重点关注cpu相关) show global status like '%cpu%'; show global status like 'threads%'; -- 线程数(过多会导致cpu高) show global status like 'queries'; -- 总查询数 show global status like 'slow_queries'; -- 慢查询数
3. 临时处理:终止耗cpu的线程(紧急情况)
如果发现某个sql长时间运行且消耗大量cpu,可临时终止:
-- 替换为实际的线程id(从processlist中获取) kill [线程id];
二、深入分析:找出cpu高的根本原因
定位到耗cpu的sql后,需要分析为什么这些sql会消耗大量cpu,常见原因包括:索引缺失、sql写法差、配置不合理、锁竞争等。
1. 检查慢查询日志(最核心的排查手段)
慢查询日志会记录执行时间超过long_query_time的sql,是排查cpu高的核心工具。
(1)开启慢查询日志(临时生效,无需重启)
-- 设置慢查询阈值(如1秒,执行超过1秒的sql会被记录) set global slow_query_log = on; set global long_query_time = 1; -- 记录未使用索引的sql(即使执行时间短,无索引也可能导致cpu高) set global log_queries_not_using_indexes = on; -- 查看慢查询日志路径 show variables like 'slow_query_log_file';
(2)分析慢查询日志
使用mysqldumpslow工具(mysql自带)分析慢查询日志:
# 查看慢查询日志路径 mysql -uroot -p -e "show variables like 'slow_query_log_file'" # 分析慢查询日志(替换为实际路径) mysqldumpslow -s t -t 10 /var/lib/mysql/xxx-slow.log
参数说明:
-s t:按执行时间排序-t 10:显示前10条最慢的sql-s c:按执行次数排序(高频低耗的sql也可能导致cpu高)
2. 分析耗cpu sql的执行计划
对找到的耗cpu sql,使用explain分析执行计划,看是否使用了索引、是否全表扫描:
-- 替换为实际的耗cpu sql explain select * from table_name where condition; -- 更详细的执行计划(包含执行成本) explain analyze select * from table_name where condition;
重点关注:
type列:如果是all(全表扫描),说明未使用索引,是cpu高的常见原因key列:显示使用的索引,如果为null,说明未使用索引rows列:预估扫描的行数,行数越多,cpu消耗越大
3. 检查mysql配置是否合理
不合理的配置也会导致cpu高,重点检查以下参数:
show variables like 'innodb_buffer_pool_size'; -- 缓冲池大小(过小会导致磁盘io高,间接引发cpu高) show variables like 'max_connections'; -- 最大连接数(过多会导致线程切换消耗cpu) show variables like 'query_cache%'; -- 查询缓存(mysql8.0已移除,开启后可能导致cpu高) show variables like 'sort_buffer_size'; -- 排序缓冲区(过大导致内存不足,频繁换页) show variables like 'join_buffer_size'; -- 连接缓冲区(同上)
4. 检查系统层面的资源竞争
cpu上下文切换:mysql线程过多会导致cpu频繁切换上下文,消耗cpu
# 查看上下文切换次数(数值过高说明有问题) vmstat 1 # 查看mysql进程的线程数 pstree -p 1972827 | wc -l
磁盘io:磁盘io高会导致mysql等待,间接拉高cpu(如swap使用、磁盘满)
# 查看磁盘io iostat -x 1 # 查看swap使用情况 free -h
三、常见原因及解决方案
| 常见原因 | 解决方案 |
|---|---|
| 无索引/索引失效 | 为查询字段添加合适的索引;检查索引是否因数据类型不匹配、函数操作失效 |
| sql写法差(如select *) | 优化sql,只查询需要的字段;避免子查询、笛卡尔积;使用join代替子查询 |
| 高频小查询 | 优化sql执行次数;增加缓存(如redis);使用批量操作 |
| 连接数过多 | 调整max_connections;排查应用侧是否有连接泄漏;使用连接池 |
| 配置不合理 | 调整innodb_buffer_pool_size(建议为物理内存的50%-70%);关闭查询缓存 |
| 锁竞争(行锁/表锁) | 优化事务,缩短锁持有时间;避免长事务;使用行锁而非表锁 |
| mysql版本问题 | 升级到稳定版本(如5.7/8.0的最新小版本),修复已知的cpu高bug |
四、长期监控:避免cpu高问题复发
开启慢查询日志(永久生效):
修改my.cnf/my.ini:
slow_query_log = on slow_query_log_file = /var/lib/mysql/mysql-slow.log long_query_time = 1 log_queries_not_using_indexes = on
重启mysql生效:systemctl restart mysqld
使用监控工具:
- percona toolkit:
pt-query-digest分析慢查询日志,pt-stalk捕获mysql性能数据 - prometheus + grafana:监控mysql cpu、内存、qps、慢查询等指标
- mysql自带工具:
mysqladmin status、show engine innodb status
定期优化:
- 定期分析慢查询日志,优化sql和索引
- 定期维护表(
analyze table更新统计信息,optimize table整理碎片) - 监控数据库增长,及时扩容或分库分表
总结
- 紧急排查:通过
show full processlist定位耗cpu的mysql线程和sql,紧急情况下可kill长时间运行的线程。 - 核心分析:开启慢查询日志,用
mysqldumpslow和explain分析sql执行计划,重点排查无索引、全表扫描、高频查询等问题。 - 长期优化:优化sql和索引、调整mysql配置、开启监控,避免cpu高问题复发。
以上就是查询mysql的cpu使用率突然变高的几种方法的详细内容,更多关于查询mysql cpu使用率变高的资料请关注代码网其它相关文章!
发表评论