db.refresh()的重复使用和db.rollback()
db.refresh()
在 SQLAlchemy 中,db.refresh()
用于从数据库中重新加载对象的状态,确保对象属性与数据库中的实际数据保持一致。下面详细介绍其使用场景和作用:
1.获取数据库生成的值
当数据库自动生成字段(如自增 ID、默认值、触发器计算的值)时,refresh
可获取这些值:
user = User(name="Alice")
db.add(user)
db.commit()
db.refresh(user) # 获取数据库分配的自增 ID
print(user.id) # 此时 ID 已从数据库加载
2. 确保读取最新数据
若其他事务可能修改了数据,可通过 refresh
强制获取最新状态:
# 用户 A 修改了数据
# 用户 B 需要获取最新状态
db.refresh(user)
print(user.status) # 获取数据库中最新的状态
3. 处理数据库触发器或默认值
当字段由数据库触发器或默认值自动填充时:
class Order(Base):__tablename__ = "orders"id = Column(Integer, primary_key=True)created_at = Column(DateTime, server_default=func.now()) # 数据库默认值order = Order()
db.add(order)
db.commit()
db.refresh(order) # 获取数据库生成的 created_at
print(order.created_at) # 显示数据库实际生成的时间
为何不需要 db.refresh()
提交后对象已同步:
db.commit()
会将所有挂起的更改写入数据库,并更新对象状态。因此,提交后对象属性已经反映了最新值,无需刷新。无外部修改:
任务在单个事务中执行,且没有其他进程或线程修改同一对象,因此对象状态始终是一致的。refresh
的适用场景:db.refresh()
主要用于以下情况:读取数据库生成的值(如自增 ID、默认值)。
确认其他事务对数据的修改。
强制刷新延迟加载的关联对象。
⭐适用场景:
1.读取数据库生成的值,比如自增ID
2.有外部修改需要刷新确认,比如有其他进程修改同一对象。
db.rollback()
db.rollback()
回滚范围:
- 最近一次
db.commit()
之后(如果有提交过)。 - 事务开始点(如果从未提交)。
解释:
db.rollback()
的回滚范围取决于数据库事务的边界和当前会话的状态。具体来说,它会撤销自当前事务开始以来所有未提交的数据库操作。
在关系型数据库中,事务是一组不可分割的操作序列,要么全部成功,要么全部失败。db.rollback()
的作用是:
- 撤销未提交的更改:将数据库状态恢复到事务开始前的状态。
- 释放事务锁:如果操作涉及锁(如写操作),回滚后会释放这些锁。
- 清空会话缓存:SQLAlchemy 会话中未提交的对象更改会被丢弃。
db.rollback():
- 每次
db.commit()
后:事务结束,数据已永久保存,后续的db.rollback()
不会影响已提交的数据。 - 异常发生时:
db.rollback()
会撤销自最近一次提交以来的所有操作。
例子:
1.如果在第一次 db.commit() 之前发生异常(例如查询失败):回滚到事务开始点(无实际影响,因为尚未提交任何更改)。
2. 如果在第一次 db.commit() 之后、第二次 db.commit() 之前发生异常(例如 get_markdown 失败):回滚 structure 的更新和 status=success 的更改,但 status=running 已提交,不受影响。
3.如果在第二次 db.commit() 之后发生异常(几乎不可能,因为已返回):不会触发此回滚。