
在使用sqlalchemy的异步会话(asyncsession)连接postgresql数据库时,开发者可能会观察到即使会话似乎已“关闭”,仍然有多个数据库连接保持开放。这通常会引起疑问:这些开放的连接是否是资源泄漏,或者存在配置问题?实际上,这并非一个问题,而是sqlalchemy连接池机制的正常工作表现,旨在优化数据库连接的性能和效率。
SQLAlchemy通过其引擎(create_async_engine)内置了连接池(Connection Pool)功能。连接池的核心思想是预先建立并维护一定数量的数据库连接,当应用程序需要连接时,直接从池中获取一个可用的连接,而不是每次都重新建立连接。当应用程序“关闭”一个连接时,该连接并不会真正断开与数据库的物理连接,而是被归还到连接池中,等待下一次复用。这种机制显著减少了连接建立和断开的开销,尤其在高并发场景下能有效提升应用性能。
默认情况下,SQLAlchemy的连接池会保持一定数量的空闲连接。对于异步引擎,这个默认数量通常是5。这意味着即使您的应用程序没有活跃的数据库操作,连接池也可能维持着5个与PostgreSQL的开放连接,以备不时之需。
如果默认的连接池大小不符合您的应用需求,您可以通过 create_async_engine 函数的 pool_size 参数进行调整。pool_size 定义了连接池中可以同时存在的最大连接数(包括正在使用的和空闲的)。
from sqlalchemy.ext.asyncio import AsyncSession, create_async_engine, async_sessionmaker
# 示例:将连接池大小设置为10
# DATABASE_URL 替换为您的实际数据库连接字符串
db_engine = create_async_engine(
'<DATABASE_URL>',
echo=False,
future=True,
pool_size=10 # 设置连接池大小为10
)
async_session = async_sessionmaker(db_engine, class_=AsyncSession, expire_on_commit=False)注意事项:
SQLAlchemy的异步会话设计了上下文管理器(async with 语句),这是管理会话生命周期的推荐方式。当您使用 async with async_session() as session: 结构时,SQLAlchemy会自动处理会话的开启和关闭(或将连接返回到连接池)逻辑。
async def get_session() -> AsyncSession:
async with async_session() as session:
# 在此代码块内,session 是一个活跃的数据库会话
# 可以执行数据库操作,例如:
# await session.execute(text("SELECT 1"))
yield session
# 当代码执行到这里,即退出 'async with' 块时,
# SQLAlchemy会自动关闭会话(如果需要)或将底层连接返回到连接池。
# 因此,显式调用 await session.close() 是不必要的,甚至可能导致逻辑混乱。在上述示例中,原始代码中的 await session.close() 是冗余的。async with 语句在退出时会确保会话资源被正确释放或回收。对于使用连接池的场景,这意味着底层数据库连接会被返回到连接池,而不是物理断开。
以下是一个结合了连接池配置和正确会话管理方式的示例:
from sqlalchemy.ext.asyncio import AsyncSession, create_async_engine, async_sessionmaker
from sqlalchemy import text
import asyncio
# 1. 配置数据库引擎和连接池
# 替换为您的实际数据库连接字符串
DATABASE_URL = "postgresql+asyncpg://user:password@host:port/database"
db_engine = create_async_engine(
DATABASE_URL,
echo=False, # 设置为True可以打印SQL语句,便于调试
future=True,
pool_size=10, # 示例:设置连接池大小为10
max_overflow=5, # 示例:允许额外创建5个连接
pool_recycle=3600 # 示例:连接每小时回收一次
)
# 2. 创建异步会话工厂
async_session = async_sessionmaker(db_engine, class_=AsyncSession, expire_on_commit=False)
# 3. 定义获取会话的依赖函数(常用于依赖注入)
async def get_db_session() -> AsyncSession:
"""
提供一个异步数据库会话,使用上下文管理器自动管理会话生命周期。
"""
async with async_session() as session:
yield session
# 4. 示例:如何使用获取到的会话执行操作
async def perform_database_operation():
async for session in get_db_session():
try:
result = await session.execute(text("SELECT version();"))
print(f"PostgreSQL Version: {result.scalar_one()}")
# 示例:执行一个事务
await session.execute(text("INSERT INTO my_table (data) VALUES ('test_data');"))
await session.commit() # 提交事务
print("数据插入成功并提交。")
except Exception as e:
await session.rollback() # 发生错误时回滚事务
print(f"数据库操作失败: {e}")
finally:
# 退出 async with 块时,会话会自动关闭或连接返回到连接池
pass
# 5. 运行示例
if __name__ == "__main__":
asyncio.run(perform_database_operation())
# 应用程序结束时,可以关闭引擎,释放所有连接
# asyncio.run(db_engine.dispose()) # 如果应用程序完全退出,可以调用此方法SQLAlchemy异步会话与PostgreSQL的连接管理通过连接池机制实现了高效的资源复用。连接在会话“关闭”后仍保持开放,是连接池的正常行为,旨在提升性能。通过合理配置 pool_size 参数,并始终使用 async with 上下文管理器来管理会话生命周期,开发者可以确保数据库连接被高效、正确地使用,从而构建出健壮且高性能的异步应用程序。避免在上下文管理器内部手动调用 session.close(),让SQLAlchemy的机制自动处理连接的回收与复用。
以上就是深入理解SQLAlchemy异步会话与PostgreSQL连接池管理的详细内容,更多请关注php中文网其它相关文章!
每个人都需要一台速度更快、更稳定的 PC。随着时间的推移,垃圾文件、旧注册表数据和不必要的后台进程会占用资源并降低性能。幸运的是,许多工具可以让 Windows 保持平稳运行。
Copyright 2014-2025 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号