thread_cache_size是mysql空闲线程缓存池大小,直接影响线程复用效率;它通过复用断开连接的线程来避免频繁创建销毁,从而显著降低cpu上下文切换开销。

thread_cache_size 设对了,能直接压低 Threads_created,减少线程创建销毁带来的上下文切换开销——这比调 max_connections 更直接影响 CPU 使用率。
thread_cache_size 是什么,为什么它管 CPU 开销?
MySQL 每次接受新连接时,若缓存里有空闲线程,就复用;否则得新建线程。新建线程涉及内存分配、栈初始化、调度注册,是实打实的 CPU 操作。而 thread_cache_size 就是这个“空闲线程池”的大小。
常见错误现象:SHOW GLOBAL STATUS LIKE 'Threads_created'; 每分钟涨几十甚至上百,SHOW PROCESSLIST 里大量 Sleep 状态连接,但 Threads_running 始终很低——说明连接来了又走,线程反复创建销毁,纯属浪费 CPU。
- 它不控制并发能力,只影响连接建立时的线程复用效率
- 值太小 → 频繁创建线程 → CPU 花在调度上,不是执行 SQL 上
- 值太大 → 内存占用略增(每个线程约 256KB 栈空间),但几乎无性能损失;不过没必要堆到 100+,边际收益极低
怎么设一个靠谱的 thread_cache_size 值?
别拍脑袋,看监控数据再调。核心指标就两个:Threads_created 和 Threads_connected。
- 先查当前值:
SHOW VARIABLES LIKE 'thread_cache_size'; - 观察 5 分钟内
Threads_created是否稳定增长:如果每分钟新增 >5,说明缓存不够 - 对比
Threads_connected的峰值:若峰值常在 80~120,thread_cache_size设为 16~32 就够用(经验值:峰值连接数的 1/4 到 1/3) - 生产环境起步建议:8 核服务器设
thread_cache_size = 16;16 核及以上可设32;超过 32 后需有明确监控依据才加
注意:thread_cache_size 不是越大越好,它只缓存“刚断开”的线程;连接空闲超 wait_timeout(默认 8 小时)后,线程自动出缓存。所以它和连接池行为是两层事——应用层用 HikariCP 控制连接复用,MySQL 层用 thread_cache_size 控制线程复用,二者要配合着看。
调完怎么验证有没有效果?
改完配置重启 MySQL(或动态生效: SET GLOBAL thread_cache_size = 32;),然后盯住两个数字:
-
SHOW GLOBAL STATUS LIKE 'Threads_created';—— 重置后观察 10 分钟增量,理想情况是趋近于 0 或个位数 -
SHOW GLOBAL STATUS LIKE 'Threads_cached';—— 这个值应稳定在你设的thread_cache_size附近,而不是长期为 0 或忽高忽低 - 顺手看下
SHOW GLOBAL STATUS LIKE 'Threads_connected';,确认没因连接池泄漏导致连接数虚高(比如应用没 close(),连接一直挂着)
如果 Threads_created 下降但 Threads_cached 始终 ≤ 2,说明连接模式有问题:可能是应用短连接没复用、或 wait_timeout 设得太小(比如 60 秒),导致线程刚进缓存就过期被踢。
容易被忽略的关联点
单独调 thread_cache_size 效果有限,它必须和下面三件事对齐:
- 应用层连接池最大连接数不能远超
max_connections,否则 MySQL 被打满,缓存再大也没线程可复用 -
wait_timeout和应用连接池的idleTimeout要匹配:比如 HikariCP 的idleTimeout=30000(30 秒),那 MySQL 的wait_timeout至少设成 60,否则连接池刚把连接放回池子,MySQL 就把它关了 - 启用线程池插件(
thread_handling = pool-of-threads)时,thread_cache_size失效——这是互斥方案,选一个深入用,别混搭
真正起效的从来不是单个参数,而是连接生命周期里每一环的衔接是否严丝合缝。线程缓存只是其中一环,但它卡在连接建立的临门一脚,调对了,CPU 曲线就能立刻松一口气。











