MySQL 8.4 LTS社区版不支持线程池功能,因许可与内核限制,INSTALL PLUGIN会报错,SHOW PLUGINS无结果,相关系统变量不存在,可用thread_cache_size等调优替代。

thread_pool.so 插件必须手动安装才能启用线程池
MySQL 8.0 社区版默认不带 thread_pool.so,即使你设了 thread_handling = 'pool-of-threads',启动时也会静默忽略——SHOW VARIABLES LIKE 'thread_handling' 显示仍是 one-thread-per-connection,但不会报错。企业版或 Percona Server 才预装该插件。
实操建议:
- 先确认插件是否存在:
SELECT PLUGIN_NAME, PLUGIN_STATUS FROM INFORMATION_SCHEMA.PLUGINS WHERE PLUGIN_NAME = 'thread_pool';,返回空则需手动安装 - 下载匹配版本的 MySQL 企业版二进制包(非源码),从
lib/plugin/目录提取thread_pool.so,拷贝到你服务器的插件目录(SELECT @@plugin_dir;查看) - 执行:
INSTALL PLUGIN thread_pool SONAME 'thread_pool.so';,成功后PLUGIN_STATUS应为ACTIVE - 再设
SET GLOBAL thread_handling = 'pool-of-threads';才真正生效
thread_pool_size 设多少才不引发调度锁争用
thread_pool_size 不是“总工作线程数”,而是线程组(group)数量;每个组独立调度连接请求。设太高会导致 THREAD_POOL_WAIT_GROUP_LOCK 等待事件飙升,反而拖慢响应。
实操建议:
- 以 CPU 逻辑核心数为基准:16 核物理 CPU(非超线程总数),起步设
thread_pool_size = 16 - 短查询为主(如 API 接口)可试
20;超过32在多数 OLTP 场景下无收益,且Thread_pool_stalled_threads易持续 > 0 - 在容器中运行时,
lscpu显示的核数 ≠ 实际可用并发能力,需查cat /sys/fs/cgroup/cpu.max或docker inspect确认限制 - 压测时紧盯
SHOW STATUS LIKE 'Thread_pool_%',若Thread_pool_idle_threads长期为 0 且Threads_running> 5,说明组内已过载
thread_pool_stall_limit 设太低会误判正常查询
这个值单位是微秒,它决定一个查询是否被标记为 “stall” 并强制移交其他线程组。设成 10000(10ms)会让简单二级索引点查也被踢出,引发频繁迁移和上下文切换。
实操建议:
- 纯 OLTP(95% 查询 thread_pool_stall_limit = 60000(60ms)
- 混合负载含报表类查询:设
200000(200ms),并配合max_execution_time = 300000控制单条语句上限 - 必须监控
Thread_pool_stalled_threads:持续 > 0 表示阈值不合理,不是调高就完事,得结合慢查询日志看是哪类 SQL 卡住 - 注意:该参数不能动态修改,需写入配置文件重启生效
启用线程池后 max_connections 仍要单独调大
线程池只改变线程复用方式,不放宽连接硬上限。max_connections 还是那个门槛,连不上就是 ERROR 1040 (HY000): Too many connections。
实操建议:
- 不要只看 CPU,先查当前连接水位:
SHOW GLOBAL STATUS LIKE 'Threads_connected';和SHOW GLOBAL STATUS LIKE 'Threads_created'; - 若
Threads_created每秒增长 > 1,说明应用层连接池没兜住,或max_connections太小 - 8GB 内存起步设
max_connections = 600,16GB+ 可设到1000–2000,但必须同步检查open_files_limit ≥ max_connections × 3(CentOS 7 默认仅 1024) -
thread_cache_size对线程池模式基本无效——线程池里没有“缓存线程”概念,只有thread_pool_idle_threads,别再盲目调这个


















