Flask中PostgreSQL连接池为何创建两个空闲连接?
PostgreSQL连接池连接数不符合预期问题
我正在开发一个用于学习的Flask应用,整体运行正常,但PostgreSQL连接池的连接数不符合预期。我使用psycopg2的SimpleConnectionPool,设置minconn=1、maxconn=10,启动时创建了1个连接。通过before_request()从池获取连接,teardown_request()将连接放回池,本应始终只有1个连接,但pgadmin显示有2个空闲连接;将minconn改为2时,启动时会出现4个连接。请问这是什么原因?
相关代码
from flask import current_app, g from psycopg2.extras import DictCursor from psycopg2 import pool import psycopg2 def database_connection(app): dsn = f'''postgresql://{current_app.config['SQL_USERNAME']}:{current_app.config['SQL_PASSWORD']}@{current_app.config['SQL_HOST']}:{current_app.config['SQL_PORT']}/{current_app.config['SQL_DATABASE']}''' pool = psycopg2.pool.SimpleConnectionPool(minconn = current_app.config['SQL_MINCONN'], maxconn = current_app.config['SQL_MAXCONN'], dsn = dsn) @app.before_request def open_connection(): if 'connection' not in g: g.connection = pool.getconn() g.connection.autocommit = True g.cursor = g.connection.cursor(cursor_factory = DictCursor) @app.teardown_request def close_connection(response): g.cursor.close() g.connection = g.pop('connection', None) if g.connection is not None: pool.putconn(g.connection) return response
问题原因与解决方案
核心原因
- Flask调试模式的重载进程:调试模式下Flask会启动两个进程——主进程和代码变更检测的重载进程,每个进程都会独立初始化自己的连接池。所以
minconn=1时两个进程各创建1个连接,最终显示2个;minconn=2时则是2×2=4个连接。 - 连接回收逻辑错误:
teardown_request中先执行g.pop('connection', None)移除了连接,后续再判断g.connection必然是None,导致连接无法正确放回池,长期运行会引发连接泄漏,进一步加剧连接数异常。
修复步骤
关闭调试重载或调试模式
开发环境需要调试的话,可关闭重载进程:if __name__ == '__main__': app.run(debug=True, use_reloader=False)生产环境直接关闭
debug模式即可。修正连接回收逻辑
先取出连接再判断,避免无效检查:@app.teardown_request def close_connection(response): if 'cursor' in g: g.cursor.close() conn = g.pop('connection', None) if conn is not None: pool.putconn(conn) return response确保连接池全局唯一
将连接池存储在app.config中,避免重复初始化:def database_connection(app): if 'db_pool' not in app.config: dsn = f'''postgresql://{app.config['SQL_USERNAME']}:{app.config['SQL_PASSWORD']}@{app.config['SQL_HOST']}:{app.config['SQL_PORT']}/{app.config['SQL_DATABASE']}''' app.config['db_pool'] = psycopg2.pool.SimpleConnectionPool( minconn=app.config['SQL_MINCONN'], maxconn=app.config['SQL_MAXCONN'], dsn=dsn ) pool = app.config['db_pool'] # 后续before_request和teardown_request逻辑不变
内容的提问来源于stack exchange,提问作者Chris
相关产品推荐
相关产品推荐

