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
相关产品推荐
相关产品推荐

