MySQL 导致 cpu 飙升的话,要怎么处理呢?
MySQL 导致 CPU 飙升是一个常见但棘手的问题,需要系统性地排查和优化。以下是我总结的处理步骤和关键点,帮助你快速定位并解决问题:
一、紧急止血(临时缓解)
-
定位问题进程
-
top -c # 按 CPU 排序,确认是否是
mysqld进程占用高 -
查看活跃连接
-
SHOW FULL PROCESSLIST; -- 查看正在执行的SQL,注意耗时长的查询
使用 KILL [id] 终止消耗资源的查询(谨慎操作)。
二、深度排查原因
-
慢查询分析(最常见原因)
-
开启慢查询日志
-
SET GLOBAL slow_query_log = 'ON'; SET GLOBAL long_query_time = 1; -- 设置超过1秒为慢查询 SET GLOBAL slow_query_log_file = '/path/to/slow.log';
-
分析慢日志
-
mysqldumpslow -s t /path/to/slow.log # 按耗时排序 pt-query-digest /path/to/slow.log # 推荐使用 Percona Toolkit
-
检查锁争用
-
SHOW ENGINE INNODB STATUS; -- 查看 "TRANSACTIONS" 和 "SEMAPHORES" 部分
-
关注
innodb_row_lock_waits和锁等待线程。 -
索引失效或缺失
-
检查执行计划
-
EXPLAIN SELECT ...; -- 分析高消耗SQL的执行计划 重点观察:type(扫描方式)、key(使用的索引)、rows(扫描行数)。
-
缺失索引检查
-
SELECT * FROM sys.schema_unused_indexes; -- 需先启用 performance_schema
-
配置与资源问题
-
检查关键参数
-
SHOW VARIABLES LIKE 'innodb_buffer_pool_size'; -- 内存是否过小? SHOW VARIABLES LIKE 'max_connections'; -- 连接数是否过多?
-
监控资源瓶颈
-
vmstat 1 # 看上下文切换(cs)和阻塞(b) iostat -dx 1 # 磁盘IO是否成为瓶颈?
-
其他可能原因
-
全表扫描:大表无索引查询。
-
排序/临时表:
ORDER BY、GROUP BY未用索引,检查Created_tmp_tables。 -
复制问题:主从延迟导致从库堆积查询。
-
Bug 或优化器缺陷:特定版本已知问题(检查 MySQL 官方 Bug 列表)。
三、针对性优化方案
1. 查询优化
-
重写低效 SQL:避免
SELECT *,拆分复杂查询。 -
强制使用索引:
FORCE INDEX (index_name)。 -
减少锁竞争:优化事务粒度,避免长事务。
2. 索引优化
ALTER TABLE orders ADD INDEX idx_customer_status (customer_id, status); -- 复合索引ALTER TABLE logs DROP INDEX unused_idx; -- 删除冗余索引
3. 配置调优
# my.cnf 调整示例 innodb_buffer_pool_size = 系统内存的70%-80% max_connections = 500 # 根据实际需求调整thread_cache_size = 50 # 减少线程创建开销
修改配置后需重启 MySQL 或动态设置(如 SET GLOBAL max_connections=500;)。
4. 架构优化
-
读写分离:将读请求分流到从库。
-
分库分表:对千万级大表进行拆分(如 ShardingSphere)。
-
缓存层:引入 Redis 缓存热点数据。
四、长效监控与防御
- 实时监控工具
-
Prometheus + Grafana:监控 QPS、连接数、慢查询率。
-
Percona Monitoring and Management (PMM):专业 MySQL 监控平台。
-
定期健康检查
-
ANALYZE TABLE orders; -- 更新统计信息 OPTIMIZE TABLE logs; -- 碎片整理(谨慎,锁表)
-
设置报警阈值
-
CPU 持续 > 80%
-
活跃连接数 > max_connections 的 70%

发表评论
所有评论