sqlalchemy 2.0+ 的 asyncsession 是生产可用的异步 orm 方案,需配合 asyncengine 和异步驱动;tortoise 适合快速原型但迁移与聚合查询易出错;gino 已停更,不建议新项目使用。

SQLAlchemy async 是生产可用的,但得用 2.0+ 和 AsyncSession
很多人试了 SQLAlchemy 1.x 的 async 尝试(比如用 await 调 session.query()),结果报 RuntimeError: This event loop is already running 或直接同步阻塞——因为 1.x 根本没真正的异步 ORM 层。SQLAlchemy 2.0+ 才通过 AsyncSession + create_async_engine() 提供完整异步支持,底层依赖 asyncpg(PostgreSQL)或 aiomysql(MySQL)等异步驱动。
实操建议:
- 必须用
sqlalchemy>=2.0.0,且显式创建AsyncEngine和AsyncSession,不能混用同步Session -
select()构建查询后,必须用session.execute()+await result.scalars().all(),不是.all()直接调 - 关系加载要主动用
selectinload()或joinedload(),lazy='select'在 async 下会触发隐式同步查询,容易卡住 - 事务必须用
async with session.begin():,裸session.commit()会报错
Tortoise ORM 适合快速原型,但字段定义和迁移逻辑容易反直觉
它语法像 Django ORM,写起来快,class User(Model): name = fields.CharField(max_length=50) 这种声明很顺手。但它不是基于 SQLAlchemy 的抽象层,而是自己实现的查询生成器 + 异步驱动封装,导致一些行为偏离预期。
常见踩坑点:
立即学习“Python免费学习笔记(深入)”;
-
fields.ForeignKeyField('models.User', 'user')这种字符串引用写法,在 PyCharm 里没法跳转,重构时极易断链 - 迁移命令
tortoise-cli aerich init-db生成的迁移文件不带 SQL DDL,实际执行靠运行时解析模型 diff,出问题难排查 - 聚合查询(如
await User.all().annotate(total=Count('id')))在 PostgreSQL 上生成的 SQL 可能漏GROUP BY,需要手动加.group_by('id') - 不支持原生 JSONB 操作符(如
@>),得用raw_sql绕过
Gino 已停止维护,新项目别碰
gino 最后一次发布是 2021 年 11 月(v1.0.1),GitHub 仓库标了 Deprecated,作者明确建议迁移到 SQLAlchemy 2.0。它曾以轻量、无模型类、纯异步著称,但代价是缺失很多 ORM 基础能力:没有关系预加载、没有完整的迁移系统、没有类型安全的查询构造器。
如果你在老项目里看到它,要注意:
-
db.bind是全局引擎实例,多租户场景下无法隔离连接池 -
model.select('name').where(...)返回的是CompiledQuery,不是可 await 对象,得再套一层await db.all(query) - 和
alembic集成麻烦,官方示例用的还是自研的gino-migrate,现已无人维护
选型关键不在“谁更异步”,而在“你缺什么”
SQLAlchemy async 学习成本高,但类型提示全、调试信息准、生态工具链(Alembic、SQLModel、Pydantic 集成)成熟;Tortoise 开箱即用,但查文档常遇到“这个功能有,但没写进文档”或者“这个 bug 在 GitHub issue 里挂了两年”。Gino 现在只剩兼容性风险。
几个硬指标帮你判断:
- 要用 Alembic 做版本化迁移 → 只能选 SQLAlchemy async
- 团队熟悉 Django ORM,且不打算长期维护复杂查询 → Tortoise 更省力
- 项目已用 Pydantic v2,且想共用模型定义 → SQLAlchemy + SQLModel 或 Tortoise(后者需手动桥接)
- 需要细粒度控制连接池、超时、重试策略 → SQLAlchemy 的
AsyncEngine参数最透明
真正容易被忽略的,是异步 ORM 对测试的影响:所有单元测试都得跑在 async event loop 里,pytest-asyncio 的 scope 设置不对,session 会复用或泄漏,mock 数据库行为比同步时代更难稳定还原。










