MySQL连接池由客户端驱动或中间件实现,非MySQL服务端提供;max_connections仅设上限,不实现复用;HikariCP需合理配置maximumPoolSize(10–20起)和connectionTimeout(1000–3000ms),并启用连接检测。

MySQL 连接池不是 MySQL 自己提供的
MySQL 服务端本身不实现连接池,所谓“配置 MySQL 连接池”,实际是配置你用的客户端驱动或中间件(比如 Java 的 HikariCP、Python 的 aiomysql 连接池、Node.js 的 mysql2 + generic-pool)。直接改 my.cnf 里的 max_connections 只是放宽上限,不等于有了连接复用。
常见错误现象:Too many connections 频发,但应用 QPS 并不高;或者每次请求都新建连接,TIME_WAIT 连接堆积在应用侧。
- 真正起作用的配置都在应用代码或框架配置里,不是在 MySQL 配置文件中
-
max_connections要配合连接池最大值设 —— 池子设 50,MySQL 却只允许 30 个连接,必然报错 - MySQL 8.0+ 支持
caching_sha2_password插件,某些旧版连接池驱动不兼容,会静默降级或握手失败
HikariCP 中 maximumPoolSize 和 connectionTimeout 怎么设
Java 应用最常用 HikariCP,它的两个关键参数直接影响吞吐和故障表现:
-
maximumPoolSize建议从 10–20 开始调,不要盲目设成 100+;多数 OLTP 场景下超过 30 后性能不升反降,因为锁竞争和上下文切换开销变大 -
connectionTimeout默认 30000(30 秒),线上应缩到 1000–3000;否则一个卡住的 DNS 解析或网络抖动会让整个线程阻塞半分钟 - 必须配
connectionTestQuery=SELECT 1(MySQL 8.0.22+ 推荐用isValid(),更轻量);否则失效连接可能被返回给业务,抛出Communications link failure
示例片段(application.yml):
spring:
datasource:
hikari:
maximum-pool-size: 16
connection-timeout: 2000
connection-test-query: SELECT 1Python 异步项目用 aiomysql 创建连接池的坑
aiomysql 的 create_pool 看似简单,但几个默认值极易引发问题:
-
minsize默认 1,maxsize默认 10 —— 小流量没问题,一旦并发突增,新请求会排队等空闲连接,而不是立即创建(它不会自动扩容到maxsize以上) - 没设
pool_recycle(单位秒)的话,长连接可能因 MySQL 的wait_timeout(默认 28800 秒)被服务端主动断开,下次复用时报Lost connection to MySQL server during query - 务必显式传
autocommit=True;否则每个execute都隐式开启事务,连接归还池时若未提交/回滚,会触发RuntimeError: Connection is not returned to pool
正确初始化示意:
pool = await aiomysql.create_pool(
host='db',
port=3306,
user='app',
password='xxx',
db='mydb',
minsize=5,
maxsize=20,
pool_recycle=3600, # 1小时强制重连一次
autocommit=True
)连接池共享导致的事务隔离问题
多个请求共用一个连接池,但事务不能跨连接传递 —— 这是最容易被忽略的逻辑陷阱。
- 你在 A 请求里开了事务、执行了
UPDATE,但没提交就 return;连接被归还池子,下次被 B 请求取走,B 的 SQL 就会运行在残留的事务上下文中,可能意外提交或回滚 - Django 默认每请求一个数据库连接,但用了连接池后,如果手动调
transaction.atomic()又没写完就退出,连接里的事务状态会污染后续请求 - Go 的
database/sql包里,Begin()返回的是带状态的*Tx,不是从池里取新连接;但如果你误把*Tx当普通*sql.DB用,会 panic 或静默失败
核心原则:事务生命周期必须严格绑定到单次请求或明确的作用域,不能依赖连接池自动清理。显式 commit 或 rollback 是唯一可靠方式。



















