异步 SQLAlchemy + 连接池:async engine + pool_pre_ping + pool_recycle

一句话:SQLAlchemy 是 Python 最流行的 ORM 库,支持同步和异步操作。异步 SQLAlchemy 避免阻塞事件循环,连接池管理数据库连接复用。在 AI 应用中,常用于异步操作数据库。

1. 异步 SQLAlchemy 基础

1.1 安装

 
pip install sqlalchemy[asyncio]
 
# 异步驱动
 
pip install asyncpg  # PostgreSQL
 
pip install aiosqlite  # SQLite
 

1.2 异步引擎

 
from sqlalchemy.ext.asyncio import create_async_engine, AsyncSession
 
from sqlalchemy.orm import sessionmaker
 
# 异步引擎
 
engine = create_async_engine(
 
    "postgresql+asyncpg://user:pass@localhost/db",
 
    echo=True,  # SQL日志
 
    pool_size=10,  # 连接池大小
 
    max_overflow=20,  # 最大溢出连接
 
    pool_pre_ping=True,  # 连接前ping检测
 
    pool_recycle=3600,  # 连接回收时间(秒)
 
)
 
# 异步会话工厂
 
async_session = sessionmaker(
 
    engine,
 
    class_=AsyncSession,
 
    expire_on_commit=False
 
)
 

2. 连接池配置

2.1 连接池参数


graph TD

    A[连接池配置] --> B[pool_size: 10]

    A --> C[max_overflow: 20]

    A --> D[pool_pre_ping: True]

    A --> E[pool_recycle: 3600]

    A --> F[pool_timeout: 30]

    B --> B1[核心连接数]

    C --> C1[超出核心的连接数]

    D --> D1[连接前检测存活]

    E --> E1[连接最大存活时间]

    F --> F1[获取连接超时]

2.2 详细配置

 
engine = create_async_engine(
 
    "postgresql+asyncpg://user:pass@localhost/db",
 
    # 连接池配置
 
    pool_size=10,  # 核心连接数(默认5)
 
    max_overflow=20,  # 超出核心的连接数(默认10)
 
    pool_pre_ping=True,  # 连接前ping检测(推荐True)
 
    pool_recycle=3600,  # 连接回收时间(秒,默认-1不回收)
 
    pool_timeout=30,  # 获取连接超时(秒,默认30)
 
    pool_use_lifo=True,  # 后进先出(推荐True)
 
    # 连接参数
 
    connect_args={
 
        "server_settings": {
 
            "application_name": "myapp",
 
        }
 
    }
 
)
 

2.3 pool_pre_ping 的作用

 
# 解决:pool_pre_ping 在每次获取连接前发送 SELECT 1 检测
 
engine = create_async_engine(
 
    "postgresql+asyncpg://user:pass@localhost/db",
 
    pool_pre_ping=True,  # ✅ 推荐开启
 
)
 

2.4 pool_recycle 的作用

 
# 解决:pool_recycle 定期回收连接
 
engine = create_async_engine(
 
    "postgresql+asyncpg://user:pass@localhost/db",
 
    pool_recycle=3600,  # 每小时回收一次
 
)
 

3. 基础用法

3.1 模型定义

 
from sqlalchemy import Column, Integer, String, DateTime
 
from sqlalchemy.orm import DeclarativeBase
 
from datetime import datetime
 
class Base(DeclarativeBase):
 
    pass
 
class User(Base):
 
    __tablename__ = "users"
 
    id = Column(Integer, primary_key=True, index=True)
 
    name = Column(String(50), nullable=False)
 
    email = Column(String(100), unique=True, nullable=False)
 
    created_at = Column(DateTime, default=datetime.utcnow)
 

3.2 异步CRUD

 
from sqlalchemy.ext.asyncio import AsyncSession
 
from sqlalchemy import select
 
# 创建
 
async def create_user(session: AsyncSession, name: str, email: str):
 
    user = User(name=name, email=email)
 
    session.add(user)
 
    await session.commit()
 
    await session.refresh(user)
 
    return user
 
# 查询
 
async def get_user(session: AsyncSession, user_id: int):
 
    result = await session.execute(
 
        select(User).where(User.id == user_id)
 
    )
 
    return result.scalar_one_or_none()
 
# 更新
 
async def update_user(session: AsyncSession, user_id: int, name: str):
 
    user = await get_user(session, user_id)
 
    if user:
 
        user.name = name
 
        await session.commit()
 
    return user
 
# 删除
 
async def delete_user(session: AsyncSession, user_id: int):
 
    user = await get_user(session, user_id)
 
    if user:
 
        await session.delete(user)
 
        await session.commit()
 

4. FastAPI集成

4.1 依赖注入

 
from fastapi import FastAPI, Depends
 
from sqlalchemy.ext.asyncio import AsyncSession
 
app = FastAPI()
 
async def get_session():
 
    """获取数据库会话"""
 
    async with async_session() as session:
 
        try:
 
            yield session
 
        finally:
 
            await session.close()
 
@app.post("/users/")
 
async def create_user(
 
    name: str,
 
    email: str,
 
    session: AsyncSession = Depends(get_session)
 
):
 
    user = await create_user(session, name, email)
 
    return {"id": user.id, "name": user.name}
 

4.2 会话管理

 
from contextlib import asynccontextmanager
 
@asynccontextmanager
 
async def get_session_context():
 
    """会话上下文管理器"""
 
    session = async_session()
 
    try:
 
        yield session
 
        await session.commit()
 
    except Exception:
 
        await session.rollback()
 
        raise
 
    finally:
 
        await session.close()
 
# 使用
 
async def example():
 
    async with get_session_context() as session:
 
        user = await create_user(session, "Alice", "alice@example.com")
 
        # 会话自动提交或回滚
 

5. 高级特性

5.1 批量操作

 
from sqlalchemy import insert
 
async def bulk_create_users(session: AsyncSession, users_data: list):
 
    """批量创建用户"""
 
    await session.execute(
 
        insert(User),
 
        users_data
 
    )
 
    await session.commit()
 

5.2 关系查询

 
from sqlalchemy.orm import selectinload
 
async def get_user_with_posts(session: AsyncSession, user_id: int):
 
    """查询用户及其文章"""
 
    result = await session.execute(
 
        select(User)
 
        .options(selectinload(User.posts))  # 预加载关系
 
        .where(User.id == user_id)
 
    )
 
    return result.scalar_one_or_none()
 

5.3 事务管理

 
async def transfer_money(session: AsyncSession, from_id: int, to_id: int, amount: int):
 
    """转账事务"""
 
    async with session.begin():
 
        # 获取账户
 
        from_account = await session.get(Account, from_id)
 
        to_account = await session.get(Account, to_id)
 
        # 检查余额
 
        if from_account.balance < amount:
 
            raise ValueError("余额不足")
 
        # 执行转账
 
        from_account.balance -= amount
 
        to_account.balance += amount
 
        # 自动提交或回滚
 

6. 性能优化

6.1 连接池监控

 
from sqlalchemy import event
 
@event.listens_for(engine.pool, "checkout")
 
def on_checkout(dbapi_conn, connection_rec, connection_proxy):
 
    """连接获取事件"""
 
    print(f"获取连接: {dbapi_conn}")
 
@event.listens_for(engine.pool, "checkin")
 
def on_checkin(dbapi_conn, connection_rec):
 
    """连接归还事件"""
 
    print(f"归还连接: {dbapi_conn}")
 

6.2 查询优化

 
# 使用 loaded_options 预加载
 
from sqlalchemy.orm import selectinload
 
async def get_user_optimized(session: AsyncSession, user_id: int):
 
    """优化查询"""
 
    result = await session.execute(
 
        select(User)
 
        .options(
 
            selectinload(User.posts),
 
            selectinload(User.comments)
 
        )
 
        .where(User.id == user_id)
 
    )
 
    return result.scalar_one_or_none()
 

7. 常见坑点

1. 忘记关闭会话

 
# 错误:未关闭会话导致连接泄漏
 
async def bad_example():
 
    session = async_session()
 
    user = await create_user(session, "Alice", "alice@example.com")
 
    # 忘记关闭会话
 
# 正确:使用async with或try/finally
 
async def good_example():
 
    async with async_session() as session:
 
        user = await create_user(session, "Alice", "alice@example.com")
 

2. 连接池耗尽

 
# 解决:调整连接池大小或使用异步锁
 
import asyncio
 
semaphore = asyncio.Semaphore(10)  # 限制并发数
 
async def limited_create_user(name: str, email: str):
 
    async with semaphore:
 
        async with async_session() as session:
 
            return await create_user(session, name, email)
 

3. 连接超时

 
# 解决:开启pool_pre_ping
 
engine = create_async_engine(
 
    "postgresql+asyncpg://user:pass@localhost/db",
 
    pool_pre_ping=True,  # ✅ 连接前检测
 
)
 

核心要点

 
from sqlalchemy.ext.asyncio import create_async_engine, AsyncSession
 
from sqlalchemy.orm import sessionmaker
 
# 异步引擎
 
engine = create_async_engine(
 
    "postgresql+asyncpg://user:pass@localhost/db",
 
    pool_size=10,
 
    pool_pre_ping=True,
 
    pool_recycle=3600,
 
)
 
# 异步会话
 
async_session = sessionmaker(engine, class_=AsyncSession)
 
# CRUD
 
async with async_session() as session:
 
    # 创建
 
    user = User(name="Alice", email="alice@example.com")
 
    session.add(user)
 
    await session.commit()
 
    # 查询
 
    result = await session.execute(select(User).where(User.id == 1))
 
    user = result.scalar_one_or_none()
 

▶ 对应原理:10-SQLAlchemy2.0异步集成

速记卡(面试闪卡)

Q1:一句话讲清「异步 SQLAlchemy + 连接池:async engine + pool_pre_ping + pool_recycle」到底是什么?

A:异步 SQLAlchemy 用 async engine 避免阻塞事件循环,连接池复用数据库连接并自动保活。

Q2:2. 连接池配置 —— 怎么理解?

A:像租车行备车:pool_size 常备车、max_overflow 高峰期加车、pre_ping 出车前试引擎、recycle 定时报废旧车(Connection Pool)。

Q3:3. 基础用法 —— 怎么理解?

A:像用模型填表:DeclarativeBase 定义 User 表,AsyncSession 里 await 增删改查,commit/refresh 落库(ORM CRUD)。

Q4:4. FastAPI集成 —— 怎么理解?

A:像依赖注入取连接:get_session 用 async with 管会话生命周期,路由里 Depends 拿到 AsyncSession 直接用(FastAPI Dependency)。

Q5:5. 高级特性 —— 怎么理解?

A:像进阶操作:bulk 批量插、selectinload 预加载关系防 N+1、async with session.begin() 管事务(Transaction)。

Q6:核心速记主线有哪些?

  • 异步引擎:create_async_engine + AsyncSession,不阻塞事件循环

  • 连接池:pool_size/max_overflow/pre_ping/recycle 四件套

  • 用法:声明模型 + await CRUD,commit/refresh 落库

  • 集成:依赖注入管会话生命周期,事务用 begin()

口诀

A:异步引擎不堵塞,AsyncSession 来

连接池,四参数,保活回收不超时

模型 CRUD,await 提交刷新落库

依赖注入取会话,事务 begin 稳如故

相关链接

相关链接