引起MySQL CPU 使用率过高常见因素和解决方案
MySQL CPU 使用率过高可能的因素及解决方案:
🚨 常见引起 MySQL CPU 过高的因素
因素 | 描述 | 是否会引起 CPU 高 |
---|---|---|
慢查询 | 大量慢 SQL 占用资源 | ✅ 是 |
全表扫描 | 查询未使用索引 | ✅ 是 |
排序/分组操作 | ORDER BY 、GROUP BY 、DISTINCT | ✅ 是 |
JOIN 操作复杂 | 多表连接或无索引关联 | ✅ 是 |
临时表频繁使用 | 如 CREATE TEMPORARY TABLE 或内存不足时磁盘临时表 | ✅ 是 |
子查询效率低 | 特别是无法优化的嵌套子查询 | ✅ 是 |
锁竞争 | 行锁、表锁等待导致并发阻塞 | ❗可能间接引发 CPU 上升(大量重试) |
配置不合理 | 如缓冲池过小、并发连接数过高 | ✅ 是 |
查询缓存失效(MySQL 8.0 已移除) | 不合理使用导致频繁失效和重建 | ⚠️ 可能 |
大量短连接 | 创建销毁连接消耗资源 | ✅ 是 |
数据库并发压力大 | 高并发请求下处理不过来 | ✅ 是 |
🔍 详细分析与解决方案
1. 慢查询 / 全表扫描
-
表现:
SHOW PROCESSLIST;
中出现大量Sending data
状态。EXPLAIN
显示 [type=ALL](file:///Users/bjsttlp200/tech_code/excalibur/public-service/public-provider/src/main/java/com/ty/pt/enums/RoleType.java#L9-L9) 或Using filesort
。
-
解决办法:
- 添加合适的索引。
- 优化 SQL 结构,避免
SELECT *
。 - 使用覆盖索引减少回表。
2. 排序 & 分组操作
-
表现:
- 出现
Using filesort
、Using temporary
。
- 出现
-
解决办法:
- 对
ORDER BY
和GROUP BY
字段加索引。 - 尽量避免在大结果集上进行排序。
- 合理设置
sort_buffer_size
、join_buffer_size
。
- 对
3. JOIN 操作复杂
-
表现:
- 多张大表关联,执行计划显示多次扫描。
-
解决办法:
- 确保关联字段有索引。
- 避免多层嵌套 JOIN。
- 考虑数据冗余或拆分逻辑。
4. 临时表使用频繁
-
表现:
- 执行计划中出现
Using temporary
。 - 内存临时表转为磁盘临时表(性能下降明显)。
- 执行计划中出现
-
解决办法:
- 优化查询逻辑,减少中间结果。
- 设置更大的
tmp_table_size
和max_heap_table_size
。 - 避免对大表做
DISTINCT
、GROUP BY
。
5. 子查询效率低
-
表现:
- 子查询嵌套层级深,无法命中索引。
-
解决办法:
- 改写为
JOIN
查询。 - 使用物化视图或中间表预计算。
- 改写为
6. 锁竞争严重
-
表现:
- 多个线程处于
Waiting for table metadata lock
。 SHOW ENGINE INNODB STATUS
中出现死锁日志。
- 多个线程处于
-
解决办法:
- 缩短事务执行时间。
- 避免长事务或批量更新。
- 适当调整
innodb_lock_wait_timeout
。
7. 配置不合理
- 关键参数建议:
参数名 | 建议值(根据机器配置调整) |
---|---|
innodb_buffer_pool_size | 物理内存的 50%~80% |
query_cache_type / query_cache_size | MySQL 8.0 已移除,不建议使用 |
thread_cache_size | 根据连接数动态调整 |
table_open_cache | 提高打开表的缓存数量 |
tmp_table_size / max_heap_table_size | 提高以支持更大内存临时表 |
8. 大量短连接
-
表现:
Threads_created
持续增长。SHOW STATUS LIKE 'Threads_created';
-
解决办法:
- 使用连接池(如 Druid、HikariCP)。
- 调整
thread_cache_size
。
9. 数据库并发压力大
-
表现:
SHOW STATUS LIKE 'Threads_running';
数值持续偏高。- CPU 持续接近 100%。
-
解决办法:
- 限流降级前端请求。
- 读写分离,引入从库。
- 使用缓存(如 Redis)减少 DB 请求。
🛠️ 常用排查命令
-- 查看当前活跃线程
SHOW FULL PROCESSLIST;-- 查看系统状态
SHOW STATUS;-- 查看 InnoDB 状态
SHOW ENGINE INNODB STATUS;-- 查看慢查询日志是否开启
SHOW VARIABLES LIKE 'slow_query_log';
SHOW VARIABLES LIKE 'long_query_time';-- 查看线程运行情况
SHOW STATUS LIKE 'Threads_running';
SHOW STATUS LIKE 'Threads_created';
✅ 总结建议
场景 | 建议措施 |
---|---|
CPU 高 + 查询慢 | 优先优化 SQL、加索引 |
CPU 高 + 并发高 | 引入缓存、读写分离 |
CPU 高 + 配置低 | 调整 buffer pool、连接池 |
CPU 高 + 锁竞争 | 优化事务、减少锁粒度 |