MySQL 应用端连接池不是 MySQL 自己配的
MySQL 服务本身不提供连接池功能,
connection pool是应用层(如 Java 的 HikariCP、Python 的 SQLAlchemy + connection pooling、Go 的
sql.DB)或中间件(如 ProxySQL、MaxScale)实现的。MySQL 只负责接受、验证、处理连接请求,并通过
max_connections等参数限制并发上限。误以为在
my.cnf里配“连接池”,常导致配置失效或资源错配。
关键 MySQL 服务端参数必须调优
即使连接池在应用侧,MySQL 仍需配合调整,否则池内连接会频繁超时、中断或被强制杀掉:
max_connections:设为略高于应用所有实例连接池
maxPoolSize总和(例如 4 个服务实例 × 每个池最大 50 连接 = 200,建议设
max_connections = 250)
wait_timeout和
interactive_timeout:默认 28800 秒(8 小时),但连接池通常复用连接数小时;若设太小(如 60),空闲连接会被 MySQL 主动断开,池内连接变
invalid,下次使用抛
MySQL server has gone away
connect_timeout:影响连接建立失败判定,连接池重试逻辑依赖它;建议保持默认 10,避免过早放弃建连
max_connect_errors:若应用频繁启停或测试环境乱填密码,可能触发主机被锁;开发/测试可设大些(如
100),生产建议保留默认
100并监控
Aborted_connects
HikariCP(Java)与 MySQL 配合的典型陷阱
最常见问题是连接池健康检查与 MySQL 超时参数不匹配,导致“看似可用实则失效”的连接被分配给业务线程:
不要用connectionTestQuery = SELECT 1(旧版驱动兼容性差,且不校验连接状态);应启用
connectionInitSql = SELECT 1或更推荐——开启
connection-test-query为
SELECT 1同时设置
validation-timeout=3000
idle-timeout必须 小于 MySQL 的
wait_timeout(例如 MySQL 设 1800,则 HikariCP 设
idle-timeout=1500),否则空闲连接在归还池前就被 MySQL 断开了
max-lifetime建议设为
1800000(30 分钟),避免长生命周期连接因网络抖动、中间设备超时等意外僵死 驱动 URL 加上
?useSSL=false&serverTimezone=UTC&allowPublicKeyRetrieval=true(MySQL 8.0+ 必须显式指定时区和公钥获取)
如何验证连接池是否真健康
光看应用日志“Connected”没用,得查实际行为:
MySQL 侧执行SHOW PROCESSLIST,观察
Command列是否大量为
Sleep,且
Time接近
wait_timeout—— 若是,说明池未及时清理或回收策略不合理 监控
Threads_connected和
Threads_created:后者持续上涨说明连接反复新建,池没生效(常见于每次 DAO 都 new DataSource) 应用侧打开 HikariCP 的
metricRegistry,重点盯
hikaricp.connections.acquire耗时突增——往往意味着 MySQL 连接数打满,新连接在排队 抓包或开启 MySQL
general_log(仅调试),确认应用发来的确实是复用连接(相同
thread_id多次执行不同 SQL),而非每次都
Connect → Query → Quit
连接池不是设了
maxPoolSize就万事大吉;MySQL 服务端容忍度、应用池回收节奏、网络稳定性三者必须咬合。一个参数偏移,就可能让池变成“假池”。
