django 4.2 默认无连接池,conn_max_age 仅控制单连接空闲存活时间,不提供连接复用调度、最大连接数限制或健康检查;高并发下仍易触发“too many connections”或“server closed the connection unexpectedly”错误。

Django 4.2 默认不内置数据库连接池,直接复用 CONN_MAX_AGE 的持久连接无法真正解决高并发下的连接耗尽或超时问题——它只是让单个请求结束后不立刻关闭连接,但连接仍由 Django 自己管理、不复用、不预热、不主动健康检查。
为什么 CONN_MAX_AGE 不是连接池
Django 的 CONN_MAX_AGE 只控制“连接空闲多久后关闭”,不提供连接复用调度、最大连接数限制、连接获取超时、自动重连等池化能力。当并发突增时,仍会频繁创建/销毁连接,容易触发数据库的 max_connections 限制或网络层 timeout(如 PostgreSQL 的 connect_timeout 或 MySQL 的 wait_timeout)。
-
CONN_MAX_AGE=0:每次请求都新建连接 → 高开销,易超时 -
CONN_MAX_AGE=60:连接最多复用 60 秒 → 无法控制并发连接数上限,空闲连接可能被 DB 主动断开(导致下次复用时报server closed the connection unexpectedly) - 无连接等待队列 → 获取连接时若全忙,直接阻塞或抛出异常(取决于底层驱动),Django 不捕获也不重试
用 django-db-geventpool 替代默认后端(推荐 PostgreSQL + gevent 场景)
这是目前 Django 4.2 兼容性最好、侵入最小的连接池方案,基于 psycopg + gevent,适合部署在 gunicorn + gevent worker 模式下。它把连接池逻辑下沉到数据库后端,对业务代码完全透明。
- 安装:
pip install django-db-geventpool - 配置
settings.py:DATABASES = { 'default': { 'ENGINE': 'django_db_geventpool.backends.postgresql_psycopg2', 'NAME': 'mydb', 'USER': 'myuser', 'PASSWORD': 'mypass', 'HOST': 'localhost', 'PORT': '5432', 'OPTIONS': { 'MAX_CONNS': 20, # 连接池最大连接数 'MIN_CONNS': 4, # 预热连接数(启动时即建好) 'REUSE_CONNECTIONS': True, # 是否复用空闲连接(默认 True) } } } - 必须搭配
gevent使用:启动时加-k gevent(gunicorn)或确保gevent.monkey.patch_all()已调用 - 注意:不兼容
runserver(因未 patch),开发时建议切回原生后端或用django-db-geventpool的同步 fallback 模式(需额外配置CONNECTION_POOL_CLASS)
用 SQLAlchemy + pgbouncer 绕过 Django ORM 层(适合写密集/长事务场景)
当部分视图或任务需要稳定低延迟、可控超时、连接隔离(比如报表导出、数据同步),可绕过 Django 默认连接管理,用 SQLAlchemy 直连 pgbouncer(轻量级连接池代理)。这比改 Django 后端更灵活,也避免 gevent 全局 patch 带来的兼容风险。
-
pgbouncer配置关键项:[postgres] host = your-db-host port = 5432 pool_mode = transaction # 推荐,比 session 模式更省连接 max_client_conn = 1000 default_pool_size = 20
- Python 端使用示例(非 Django ORM):
from sqlalchemy import create_engine engine = create_engine( "postgresql://user:pass@localhost:6432/postgres", pool_size=10, max_overflow=5, pool_timeout=5, # 获取连接超时(秒) pool_recycle=3600, # 防止被 pgbouncer kill idle 连接 ) - 注意:此方式需手动管理 session/transaction,不能混用 Django 的
connection和该 engine;适合独立任务,不适合替换全局 ORM
真正要稳住数据库连接,关键不是“设个 CONN_MAX_AGE”,而是明确你卡在哪一环:是短连接风暴?还是慢查询拖垮连接?或是 DB 侧 timeout 设置过严?连接池只是工具,得先看 pg_stat_activity 或 SHOW PROCESSLIST,确认是连接数打满,还是连接建立阶段就失败——后者往往该调 connect_timeout 或检查网络,而不是加池子。
Python免费学习笔记(深入):立即使用
在学习笔记中,你将探索 Python 的核心概念和高级技巧!











