FastAPI + SQLAlchemy 异步会话(AsyncSession)核心方法

一、事务处理核心流程

1. 标准事务生命周期(增、删、改)

复制代码
# 顺序:标记操作 → 执行SQL并提交 → 刷新对象
async with AsyncSessionLocal() as db:
    # ① 标记操作(内存中记录,未发SQL)
    db.add(new_object)                # 新增
    await db.delete(existing_object)  # 删除
    # 或者:stmt = update(...).where(...);await db.execute(stmt)  # 更新
    
    # ② 提交事务(发送SQL到数据库,永久落盘)
    await db.commit()                 
    
    # ③ 刷新对象(可选,从数据库加载最新值,如自增ID)
    await db.refresh(new_object)      

2. 查询流程(只读操作)

复制代码
# 查询通常不需要 commit,只需执行并读取结果
result = await db.execute(select(News).where(...))  # 执行查询,返回 Result 对象
items = result.scalars().all()                       # 提取 Python 对象列表

二、各方法作用详解

方法 调用时机 作用 是否发送SQL
db.add(obj) 新增数据时 将对象标记为"待插入",加入会话的工作队列。 ❌ 否
db.add_all([obj1, obj2]) 批量新增 将多个对象标记为"待插入"。 ❌ 否
await db.delete(obj) 删除数据时 将对象标记为"待删除"。 ❌ 否
await db.execute(stmt) 执行任意SQL(含select/update/delete/insert 1. 将SQL语句发送给数据库服务器执行。 2. 返回 Result 对象(包含影响行数、游标等)。 3. 对于 update/delete,数据在数据库内存(Buffer Pool)中已变更,但事务未提交,其他连接不可见。 ✅ 是
await db.commit() 必须在所有增、删、改操作之后调用 1. 将当前事务中的所有变更(add/delete/execute永久写入磁盘 。 2. 释放数据行上的锁。 3. 使变更对其他数据库连接可见。 4. 若在此前代码抛异常且未捕获,事务会自动回滚,所有变更撤销。 ✅ 是(提交指令)
await db.refresh(obj) 调用 commit() 之后(通常是新增/更新后) 从数据库重新查询该对象的最新状态,刷新本地内存属性(如获取自增 id、数据库默认值、计算列等)。 ✅ 是(查询)
await db.rollback() 发生异常需要撤销变更时 撤销当前事务中所有未提交的变更(利用 Undo Log 回滚数据)。 ✅ 是(回滚指令)
await db.flush() commit 前需要提前获取数据库生成的ID时(极少手动调用) 提前将 SQL 发送到数据库执行(写入内存),但不提交事务 。数据仍处于当前事务中,其他连接不可见,可通过 rollback 撤销。 ✅ 是

三、事务自动管理(上下文管理器)

使用 async with AsyncSessionLocal() as db: 时,会自动 在代码块结束时执行 close()(归还连接到池)。但它不会自动 commit,仍需显式调用。

若代码块内抛异常,且未显式调用 commit,会话会在关闭时自动执行 rollback


四、result.rowcountcommit 的关系

  • result.rowcount :由 execute 执行后立即从数据库返回,表示本次 SQL 语句影响了数据库内存中的多少行 。此值不依赖 commit,即使未提交,值也已获取。

  • commit :将内存变更持久化到磁盘,并释放锁。若省略 commit,内存变更会在会话关闭时被 rollback 撤销。


五、典型代码范例(增、改、删)

1. 新增 + 获取自增ID

复制代码
new_news = News(title="标题", content="内容")
db.add(new_news)
await db.commit()           # 此时数据库已插入,ID已生成
await db.refresh(new_news)  # 将生成的ID加载到本地对象
return new_news.id

2. 更新(方式一:对象属性修改)

复制代码
result = await db.execute(select(News).where(News.id == id))
news = result.scalar_one()
news.title = "新标题"
await db.commit()  # 自动检测到对象变更,生成UPDATE发送

3. 更新(方式二:批量更新,不查询)

复制代码
stmt = update(News).where(News.category_id == 1).values(views=News.views + 1)
result = await db.execute(stmt)
await db.commit()
return result.rowcount  # 返回受影响行数

4. 删除

复制代码
news = await db.get(News, id)
if news:
    await db.delete(news)
    await db.commit()
相关推荐
这个DBA有点耶1 天前
MVCC深入:Read View、版本链与快照读——InnoDB并发控制的内核
数据库·mysql·架构
DBA_G1 天前
从地面到云霄:GBase数据库在民航三大场景的落地实践
数据库
自由能燃气设备1 天前
商用全预混低氮冷凝锅炉免费方案vs付费方案对比+选型避坑指南
大数据·数据库·人工智能
科创致远1 天前
科创致远 ESOP 系统核心效能与实战价值展示
大数据·数据库·人工智能·精益工程
2601_962218611 天前
万象生鲜系统称重自动多退少补算法解决生鲜非标品痛点
大数据·数据库·人工智能·python·算法
张洛闻Eren1 天前
k8s云原生【第十课】:水平 Pod 自动扩缩容
运维·数据库·云原生·kubernetes·github
于平安1 天前
MySQL-触发器
数据库·mysql
白远山1 天前
上海24小时自助健身房解决方案实战指南与经验分享
java·数据库·架构·需求分析
Omics Pro1 天前
斯坦福Nature+Science|广义虚拟细胞基础大模型
数据库·人工智能·算法·机器学习·自然语言处理
2603_965148111 天前
AI+API选品:下一代智能商务助手雏形已现
java·大数据·数据库·人工智能·数据挖掘