mysql高并发优化需四层协同:连接管理(启用连接池、设wait_timeout≤30秒、禁用dns解析)、锁优化(事务短小、固定表顺序、热点行分片)、索引与查询(优化慢sql、避免select*、改游标分页)、参数调优(innodb_buffer_pool_size设50%–75%内存、合理配max_connections与thread_cache_size)。

MySQL 默认配置完全扛不住高并发短连接,必须调参数、关解析、控超时、配连接池,否则刚上量就报 Too many connections 或响应毛刺明显。
为什么短连接特别吃资源?
短连接每秒建连断连几十次,光 TCP 三次握手 + MySQL 认证就耗掉 20–50ms;更致命的是每次都会创建新线程(Threads_created 持续上涨),而线程创建/销毁本身就会触发上下文切换和内存分配。8.0 虽优化了线程模型,但 thread_cache_size 设太小照样雪崩。
- 现象:
SHOW STATUS LIKE 'Threads_created'每秒涨 >5,SHOW PROCESSLIST里大量Sleep状态连接堆积 - 根本原因:没关 DNS 反向解析、
wait_timeout过长、应用没复用连接 - 关键动作:启动加
--skip-name-resolve,避免 hostname 解析阻塞;wait_timeout必须 ≤ 60 秒(建议 30)
哪些 MySQL 参数必须改?
不是所有参数都该调大,有些反而要压小——短连接场景下,“快进快出”比“多留一会儿”更重要。
-
max_connections:设为 500–1000(别盲目堆到 3000+),同时执行SET GLOBAL max_connections = 800并写入my.cnf;注意单连接内存开销 ≈ 2–3MB,800 连接至少预留 2GB 内存 -
thread_cache_size:设为 16–32(公式:8 +max_connections/100),确保空闲线程能被复用,避免频繁创建 -
back_log:设为 200–500,应对突发建连请求(TCP SYN 队列长度) -
interactive_timeout和wait_timeout:统一设为 30,防止空闲连接长期占位 -
open_files_limit:必须 ≥max_connections× 2(每个连接至少占 2 个文件描述符),系统级也要同步调:ulimit -n 65535
应用侧连接池怎么配才不拖后腿?
应用层连接池配得再好,如果和 MySQL 侧参数打架,照样打抖。重点是让池子“够用但不贪吃”,且超时必须错开层级。
- HikariCP:
maximumPoolSize别超过 100(Java 应用实例数 × 100 是上限,不是目标值);connectionTimeout设为 3000ms,必须 wait_timeout;idleTimeout设为 60000ms(≈wait_timeout× 2) - PyMySQL + DBUtils:
maxconnections建议设为 CPU 核心数 × 2 + 20,connect_timeout内网 2s、公网 5s,read_timeout和write_timeout分别设为 30s 和 10s - 致命坑:
autocommit=False在短连接场景下极易导致事务未提交就归还连接,引发锁等待;读多写少服务直接设autocommit=True
监控什么才能及时发现问题?
光看 QPS 没用,得盯住连接生命周期里的“卡点”。很多线上抖动,其实是 Threads_running 突然飙到 200+,但 Max_used_connections 才 300,说明不是连接不够,而是查询堵住了。
- 必查指标:
SHOW STATUS LIKE 'Threads_connected'(当前连接数)、SHOW STATUS LIKE 'Threads_running'(活跃线程数)、SHOW STATUS LIKE 'Aborted_connects'(失败连接数,飙升说明认证或超时问题) - 关键阈值:
Threads_running> 80% CPU 核数,基本就是查询或锁瓶颈;Aborted_connects每分钟 >5,立刻查网络或connect_timeout - 真实陷阱:
SHOW PROCESSLIST里出现大量Waiting for table flush或Waiting on mutex,说明table_open_cache或innodb_buffer_pool_size不足,不是连接池的事
真正难的不是调参,而是把“连接建立→使用→释放→回收”整个链路的耗时拆解清楚。比如你看到 connectionTimeout 超时,得先确认是网络延迟、DNS 卡住、还是 MySQL 已经在排队——这三者修复路径完全不同。











