如何在SQLAlchemy ORM提交后锁定数据表行?
解决方案:提交后重新查询并锁定行
要实现两次session.commit()之间锁定目标记录的需求,核心思路是在第一次提交后,重新通过带行锁的查询获取对象,这样就能达到和with_for_update一致的排他锁效果,阻止其他进程修改该行直到当前事务结束。
具体实现步骤
- 第一次提交后,利用对象的主键(比如
id)重新发起查询,通过with_for_update()给该行加上排他锁; - 后续对对象的修改和提交操作,基于这个被锁定的对象进行。
修改后的代码示例
import MyOrm from sqlalchemy.orm import sessionmaker from sqlalchemy import create_engine engine = create_engine(url=f'postgresql://{username}:{password}@{host}:{port}/{database}') Session = sessionmaker(bind=engine) data = {"name":"John", "number":1, "request":"registered"} with Session() as session: try: obj = MyOrm(**data) session.add(obj) # 第一次提交,将记录写入数据库并标记为已注册 session.commit() # 重新查询并锁定该行,阻止其他进程修改 obj = session.query(MyOrm).filter_by(id=obj.id).with_for_update().one() # 处理数据逻辑 process_data(obj) # 更新状态并提交 obj.request = "processed" session.commit() except Exception: session.rollback() print("completed")
关键说明
with_for_update()会在PostgreSQL中生成SELECT ... FOR UPDATE语句,给目标行加上排他锁,其他事务尝试修改或锁定该行时会被阻塞,直到当前事务完成第二次提交;- 必须通过重新查询获取锁定后的对象,因为第一次提交后,原对象虽然还在session中,但并未持有数据库行锁;
- 如果
process_data()执行时间过长,会导致锁持有时间增加,可能影响系统并发性能,需合理控制该函数的执行时长。
内容的提问来源于stack exchange,提问作者vll1990
相关产品推荐
相关产品推荐

