直接用connect()撑不住1000 qps是因为每次调用都要经历tcp三次握手、mysql身份认证和会话初始化,平均耗时20–100ms,远超web请求50ms响应目标;且mysql默认max_connections仅151,100并发即触发“too many connections”错误,连接等待队列成为性能瓶颈。

为什么直接用 connect() 会撑不住 1000 QPS?
不是代码写错了,是连接本身扛不住。每次调用 pymysql.connect() 都要走 TCP 握手 + MySQL 认证 + 初始化会话,平均耗时 20–100ms;而一个 Web 请求本该在 50ms 内返回。更致命的是:max_connections 默认只有 151,100 个并发请求就可能触发 Too many connections 错误。
常见错误现象包括:
- Flask/FastAPI 日志里反复出现
OperationalError: (1040, 'Too many connections') - MySQL
SHOW STATUS LIKE 'Threads_connected'持续接近或超过max_connections - 应用响应时间波动剧烈,但 CPU/内存并不高——瓶颈卡在连接等待队列上
SQLAlchemy 的 create_engine 默认就有连接池,但必须显式配对
很多人以为装了 SQLAlchemy 就自动“有池子”,其实默认配置极保守:pool_size=5、max_overflow=10,意味着最多只允许 15 个并发连接——远不够高并发场景。
正确做法是根据实际负载调整关键参数:
-
pool_size:常驻连接数,建议设为预期最小并发量(如 10–20) -
max_overflow:超出pool_size后可临时创建的连接数,设为pool_size × 2左右较稳妥 -
pool_timeout:获取连接超时时间,建议 3–5 秒,避免请求无限阻塞 -
pool_recycle:强制回收连接周期(秒),推荐 3600(1 小时),防止 MySQL 的wait_timeout主动断连导致Lost connection
示例配置:
engine = create_engine(
"mysql+pymysql://user:pass@localhost:3306/db",
pool_size=20,
max_overflow=40,
pool_timeout=5,
pool_recycle=3600,
pool_pre_ping=True # 每次取连接前执行 SELECT 1,自动剔除失效连接
)
用 aiomysql 做异步连接池时,minsize 和 maxsize 不是越大越好
异步池看似能扛更多并发,但盲目提高 maxsize 反而引发新问题:MySQL 单实例连接数上限仍是硬约束,且过多空闲连接会占用内存并拖慢连接验证(SELECT 1)速度。
Python 3.14.2是Python编程语言在2025年12月5日发布的稳定版本,属于3.14系列的第二个维护更新。该版本包含了18项修复,重点解决了多进程、数据类及正则表达式等模块的回归问题,并修复了CVE-2025-12084等安全漏洞。此版本标志着自由线程模式(移除GIL)正式获得官方支持,是Python发展的重要里程碑。
关键原则:
-
minsize应 ≥ 应用常驻 worker 数(如 uvicorn 的--workers 4,则minsize至少为 4) -
maxsize建议 ≤ MySQL 的max_connections × 0.7,留出空间给 DBA 监控、备份等后台任务 - 务必启用
echo=False(关闭 SQL 日志),否则异步环境下日志输出可能乱序甚至死锁
容易被忽略的一点:异步池必须配合 async with pool.acquire() 使用,直接 await pool.acquire() 而不释放,会导致连接泄漏——这点比同步池更难排查。
连接池健康检查不能只靠 pool_pre_ping,还得防 MySQL 主动断连
pool_pre_ping=True 确实能在每次取连接前执行 SELECT 1,但它无法应对一种典型场景:MySQL 因 wait_timeout(默认 28800 秒)主动关闭空闲连接,而 Python 连接池尚未感知,下次取出时直接抛 MySQL server has gone away。
真正有效的组合策略是:
- 服务端:调大 MySQL 的
wait_timeout(如设为 28800 → 86400) - 客户端:
pool_recycle设为略小于wait_timeout(如 82800),强制提前回收 - 代码层:捕获
pymysql.err.OperationalError中含gone away的异常,触发重试逻辑(注意避免无限重试)
这个三层防护缺一不可——单靠某一层,在流量突增或数据库抖动时仍会漏掉失效连接。
Python免费学习笔记(深入):立即使用
在学习笔记中,你将探索 Python 的核心概念和高级技巧!










