connectionpoolexhaustederror 表明数据库连接池已无可用连接,本质是所有连接均处于活跃状态且未归还,新请求等待超时。常见原因包括连接泄漏(如未调用session.close())、pool_size与max_overflow配置过小、长事务或未消费完查询结果导致连接被长期占用。

ConnectionPoolExhaustedError 是什么情况
这个异常通常不是 SQLAlchemy 原生抛出的,而是底层数据库驱动(比如 psycopg2 或 pymysql)在连接池中没有可用连接时,由 SQLAlchemy 的 QueuePool 或 NullPool 触发的超时失败。典型错误信息类似:sqlalchemy.exc.TimeoutError: QueuePool limit of size 5 overflow 10 reached, connection timed out, timeout 30。
本质是:所有连接都在忙(没被释放),新请求等不到空闲连接,最终超时。
检查 engine 创建时的 pool 参数是否合理
默认的 create_engine 使用 QueuePool,但参数偏保守,尤其在 Web 应用或并发高场景下容易卡住。
-
pool_size默认是 5,意思是最多只维护 5 个空闲连接;max_overflow默认是 10,表示允许额外创建最多 10 个临时连接(用完即关)。两者加起来才是“最多能同时打开多少连接” - 如果业务峰值并发远超 15,就会排队等连接,继而超时
-
pool_timeout默认 30 秒,太长,会让调用线程卡太久,不如早点失败
建议根据实际负载调整,例如:
engine = create_engine(
"postgresql://...",
pool_size=10,
max_overflow=20,
pool_timeout=5, # 5 秒拿不到连接就报错,别死等
pool_recycle=3600, # 防止连接被 DB 服务端主动断开(如 PostgreSQL 的 tcp_keepalives)
)
注意:pool_size 不是“最大连接数”,而是“常驻空闲连接数”;真正上限是 pool_size + max_overflow。
安全 Python 代码沙箱:在隔离的沙箱中执行任意 Python 代码,预装 requests、NumPy、pandas 库。返回 stdout、stderr。
确认 session 是否真的被 close() 或 return 到池里
最常见原因不是池子小,而是连接没还回去——比如忘了 session.close(),或者用了 session.remove() 却没配好 scoped session,又或者在异步上下文里误用同步 session。
- 在 Flask 中用了
scoped_session,必须配session.remove()(通常在 request teardown 里),否则 session 和底层连接会一直挂着 - 在 FastAPI 或纯脚本里手动管理
Session,务必确保每个session都执行了session.close()(推荐用with语句包裹) - 不要用
session.rollback()或session.commit()后就以为连接自动释放了——它们只提交事务,不归还连接
示例安全写法:
with Session(engine) as session:
result = session.execute(text("SELECT 1")).fetchone()
# 出 with 块时自动 close()
排查长事务或未关闭的查询游标
即使 session 关闭了,如果之前执行了大查询、流式读取(yield_per)、或没消费完 Result,底层连接可能仍被占用。
-
session.execute(...).fetchall()没问题;但.yield_per(1000)后没迭代完,连接不会释放 - 使用
connection.execution_options(stream_results=True)时,必须显式遍历或调用close() - ORM 查询中用了
lazy="dynamic",返回的是Query对象,真正执行在第一次访问时,容易漏掉
检查点:
- 日志里是否有长时间运行的 SQL(>10s)
- 数据库侧查
pg_stat_activity(PostgreSQL)或SHOW PROCESSLIST(MySQL),看是否存在 status =idle in transaction的连接 - 是否在循环里反复创建
session却没 close,比如把Session()放在 for 循环内部又没处理异常路径
连接池耗尽往往不是配置问题,而是某个地方悄悄把连接“借走不还”——得顺着日志和数据库实时状态去盯活连接。
Python免费学习笔记(深入):立即使用
在学习笔记中,你将探索 Python 的核心概念和高级技巧!










