MySQL max_connections 与 thread_cache_size 的调优经验

13次阅读

max_connections设得过高会导致连接失败,因资源超限触发OOM Killer或mysql主动拒绝;应依据Threads_connected峰值设为1.5–2倍,配合thread_cache_size(4–16)、ulimit和somaxconn协同调优。

MySQL max_connections 与 thread_cache_size 的调优经验

max_connections 设定太高反而导致连接失败

MySQL 启动时会为每个连接分配独立线程和内存(如 sort_buffer、join_buffer),max_connections 超出物理资源承载能力后,新连接可能因 Cannot allocate memoryToo many connections 被拒绝——后者是 MySQL 主动拦截,前者是 OS 层面 OOM Killer 干预。

实操建议:

  • 先查真实并发:用 SHOW STATUS LIKE 'Threads_connected'; 观察峰值,而非按应用服务器连接池大小硬设
  • 留余量但别高:线上建议设为峰值的 1.5–2 倍,超过 2000 需同步检查 ulimit -n/proc/sys/net/core/somaxconn
  • 配合连接池:应用端用 HikariCP 等时,maximumPoolSize 应 ≤ max_connections × 0.8,避免雪崩式重连

thread_cache_size 不是越大越好,多数场景 4–16 就够了

thread_cache_size 控制空闲线程缓存数量。当客户端断开,线程不立即销毁而是放入缓存;新连接到来时优先复用缓存线程,省去创建/销毁开销。但缓存过多线程会持续占用内存(每个线程约 256KB–1MB),且无实际收益。

判断是否需要调大:

  • SHOW STATUS LIKE 'Threads_created'; —— 若该值每秒增长 > 1–2,说明缓存不足,频繁创建新线程
  • 对比 Threads_cached:若长期稳定在 thread_cache_size 上限,说明当前值合理;若长期为 0 或极低,说明设高了也白搭
  • 注意负载模式:短连接高频场景(如 php CGI)比长连接(java 连接池)更依赖此参数

两个参数相互影响,必须一起看 Threads_created 和 Connections

单独调优 max_connectionsthread_cache_size 容易误判。关键要看这两个状态变量的组合关系:

  • Connections 高 + Threads_created 持续上升 → 先加 thread_cache_size,再确认是否真需扩 max_connections
  • Connections 接近 max_connectionsThreads_created 很低 → 说明连接复用好,瓶颈不在线程创建,可能是慢查询或锁等待
  • Threads_connected 波动剧烈(如 10→300→20)→ 检查应用是否未正确关闭连接,或连接池配置不当(如 idleTimeout 过长)

linux 内核限制常被忽略,导致参数失效

MySQL 的 max_connections 受限于系统级资源,即使配置文件写了 5000,也可能起不来:

  • ulimit -n 必须 ≥ max_connections + 300(预留日志、复制等后台线程)
  • /proc/sys/net/core/somaxconn 影响 TCP 连接队列长度,低于 max_connections 时会出现连接超时(尤其突发流量)
  • systemd 服务启动时默认继承 shell 的 ulimit,需在 /etc/systemd/system/mysqld.service 中显式加 LimitNOFILE=65536

改完记得 systemctl daemon-reload && systemctl restart mysqld,否则内核限制没生效,MySQL 日志里也不会报错,只会默默降级运行。

text=ZqhQzanResources