调大innodb_buffer_pool_size通常无效,因CPU 100%主因是未走索引的SQL全表扫描导致CPU计算瓶颈,而非内存不足;此时数据已在内存中,增大缓冲池无法减少行级比较开销,反而可能引发OS swap。

MySQL CPU 100% 时,物理调优(如调大 buffer_pool、tmp_table_size)往往治标不治本——真正吃 CPU 的,几乎全是没走索引的 SQL,不是内存不够。
为什么调 innodb_buffer_pool_size 通常没用?
当 CPU 打满但内存充足、磁盘 IO 不高时,说明数据基本已在内存里,瓶颈不在“读不到”,而在“算不动”。innodb_buffer_pool_size 调再大,SELECT * FROM huge_table WHERE unindexed_col = ? 还是得扫百万行、做百万次比较——CPU 就是这么烧出来的。
常见误操作:
- 看到 CPU 高就盲目把
innodb_buffer_pool_size设成物理内存的 75%,结果 OS 开始 swap,反而更慢 - 调大
tmp_table_size和max_heap_table_size,让原本该落盘的临时表继续在内存里狂排序,CPU 更烫 -
thread_cache_size调太高,线程创建销毁开销没减少,反而增加调度负担
哪些物理参数值得动?动之前先确认什么
只有两类场景才需谨慎调整物理参数:
-
确认是后台线程在刷脏页或 purge 导致 CPU 高:查
SHOW ENGINE INNODB STATUS里 “BACKGROUND THREAD” 和 “FILE I/O” 部分,若srv_master_threadloops/sec 异常高,且OS WAIT ARRAY INFO中 signal count 远大于 reservation count,说明 purge 压力大 → 可适度调大innodb_purge_threads(如从 1 改为 4) -
大量小查询反复创建隐式临时表:执行
SHOW GLOBAL STATUS LIKE 'Created_tmp%',若Created_tmp_disk_tables/Created_tmp_tables> 0.1,且 EXPLAIN 显示Using temporary,才考虑同步调大tmp_table_size和max_heap_table_size(必须等值设置)
注意:long_query_time 是浮点数,设成 '1' 字符串会静默失败;slow_query_log 动态开启后,日志路径由 slow_query_log_file 决定,别假设它一定在 /var/lib/mysql/ 下。
真正该优先做的物理层动作:关掉无效功能
有些“物理开关”开着就是在给 CPU 加负重:
- 关闭
query_cache_type = 0(MySQL 8.0+ 已移除,但 5.7 环境仍常见)—— 查询缓存锁表争用严重,QPS 稍高就成 CPU 杀手 - 禁用
innodb_stats_on_metadata = OFF—— 否则每次SHOW TABLE STATUS或连接时查 information_schema 都触发统计更新,小表没事,大表直接卡住元数据锁 - 审计日志(audit log)若非合规必需,设
audit_log_policy = NONE—— 每条语句额外序列化+写磁盘,CPU 和 IO 双杀
最后提醒一句:所有 SET GLOBAL 参数修改只对新连接生效,老连接仍按旧值运行。你看到 CPU 下降,大概率是因为慢查询被 kill 或自然结束,不是参数生效了。


















