You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

SQLAlchemy AsyncSession执行查询未提交为何默认回滚?

问题解答

原因说明

SQLAlchemy的AsyncSession(包括同步Session)在通过上下文管理器(async with)退出时,若当前存在未提交的事务,会自动执行回滚操作。这是框架的默认行为,目的是防止未完成的事务残留,确保数据一致性——哪怕你只执行了只读查询,会话默认也会开启事务,因此退出时会触发回滚逻辑。

你看到的回滚并非“撤销了查询结果”,只是结束当前未提交的事务,已经获取到的db_users数据不会受到任何影响。

解决方案

针对只读查询场景,有以下几种处理方式:

1. 直接移除commit()(推荐)

只读操作完全不需要提交事务,自动回滚只是会话的正常收尾流程,不影响已获取的查询结果。修改后的print_users函数:

from sqlalchemy import select
from db.schemas import Users
from db.database import async_session

async def print_users() -> None:
    async with async_session() as session:
        result = await session.execute(select(Users))
        db_users = result.scalars().all()

        for u in db_users:
            print(u)
        
        # 移除不必要的commit()

2. 显式开启只读事务

如果想更明确地标记这是只读操作,可以在会话内开启只读事务,让流程逻辑更清晰:

async def print_users() -> None:
    async with async_session() as session:
        async with session.begin(read_only=True):  # 开启只读事务
            result = await session.execute(select(Users))
            db_users = result.scalars().all()

            for u in db_users:
                print(u)
    # 上下文退出时仍会自动回滚,但只读事务的回滚无任何副作用

3. 调整会话配置(可选)

若希望默认会话不自动开启事务,可在创建async_sessionmaker时设置autocommit=True,但这种方式不推荐用于大多数场景,因为会改变会话的默认事务行为,可能引发其他问题:

# db/database.py中修改
async_session = async_sessionmaker(bind=engine, autocommit=True)

总结

你之前添加的commit()完全多余,直接移除即可。自动回滚是SQLAlchemy的正常机制,不会影响你的查询结果,无需担心。

内容的提问来源于stack exchange,提问作者user13726908

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.23 16:17:16