thread_cache_size无命中率指标,真实依据是threads_created与threads_cached趋势;若threads_created持续升高(如>10/s)且threads_cached长期≤2,需调大该值,生产建议设为8+(max_connections/100),上限32。

thread_cache_size 本身不产生命中率指标,所谓 “ThreadCacheHitRate 降低” 是误读——MySQL 没有 ThreadCacheHitRate 这个状态变量。真实反映线程复用效果的是 Threads_created 和 Threads_cached 的比值趋势。如果每秒 Threads_created 持续升高(比如 > 10/s),说明大量连接在反复创建/销毁线程,此时才需要调优 thread_cache_size。
thread_cache_size 设置过小导致频繁线程创建
- 现象:
SHOW STATUS LIKE 'Threads_created';值持续快速上涨,SHOW STATUS LIKE 'Threads_cached';长期为 0 或极低(如 ≤ 2) - 原因:MySQL 每次新建连接时,若缓存池已满或为 0,就直接 fork 新线程;连接断开后,仅当
thread_cache_size有余量才缓存,否则直接销毁 - 实操建议:
- 先查当前负载下的连接波动:运行
watch -n 1 'mysql -e "SHOW STATUS LIKE \"Threads%\";"'观察 30 秒内Threads_created增量 - 若平均每秒新增 > 5 个线程,
thread_cache_size至少设为max_connections × 0.05(例如max_connections = 500→ 起始值设 25) - 生产环境可参考公式:
thread_cache_size = 8 + (max_connections / 100),上限建议不超过 32(过高反而增加管理开销) - 修改后无需重启:执行
SET GLOBAL thread_cache_size = 24;
- 先查当前负载下的连接波动:运行
thread_cache_size 设置过大反而浪费资源
- 现象:
Threads_cached长期接近thread_cache_size,但Threads_created几乎为 0,同时mysqld进程 RSS 内存明显偏高 - 原因:每个缓存线程即使空闲也占用栈空间(默认 256KB),32 个空闲线程 ≈ 8MB 内存“静默吃掉”
- 实操建议:
- 检查是否真有高频连接波动:用
pt-online-schema-change或应用侧连接池日志确认连接建立频率 - 如果应用使用连接池(如 HikariCP、Druid),且
min-idle ≥ 5,thread_cache_size设为 4–8 即可,不必匹配最大连接数 - 避免盲目设成 64 或 128:曾有案例将该值设为 128 后,空闲线程占满 30MB 内存,却未降低任何 CPU 开销
- 检查是否真有高频连接波动:用
为什么调了 thread_cache_size 仍没改善 CPU 使用率
- 常见错误:把线程创建开销和 CPU 高负载混为一谈。线程创建消耗的是系统调用和内存分配时间,不是主要 CPU 占用源
- 真正要排查的:
-
SHOW PROCESSLIST;中是否存在大量State: Sending data或Sorting result的长查询 -
SHOW ENGINE INNODB STATUS\G中的SEMAPHORES区段是否显示os_waits高(说明锁争用严重) -
innodb_thread_concurrency是否为 0(等于不限制,可能引发内核态线程调度风暴)
-
- 关键动作:
- 先禁用无关监控:执行
SET GLOBAL innodb_stats_on_metadata = 0;,防止information_schema查询拖垮元数据性能 - 若
Threads_created已稳定在较低水平(如 innodb_buffer_pool_size、慢查询优化或读写分离
- 先禁用无关监控:执行
thread_cache_size 是“止血贴”,不是“强心针”。它只解决连接潮汐带来的线程抖动,对 SQL 效率、索引缺失、锁冲突、缓冲池不足等问题完全无效。调之前,务必先确认 Threads_created 确实在涨——否则所有调整都是在掩盖真正的问题。











