SqlAlchemy锁定2个表中的外部行

时间:2017-08-23 10:22:58

标签: python sql postgresql sqlalchemy locking

我的数据库中有2个sqlalchemy模型(postgresql 9.5)。

class AModel(Model):
    id = db.Column(db.Integer, primary_key=True)

class BModel(Model):
    id = db.Column(db.Integer, primary_key=True)
    a_id = db.Column(db.ForeignKey('amodel.id'), index=True)
    a = db.relationship('AModel', backref=db.backref('bmodel'))

现在我想锁定记​​录BModel以进行更新(但我还想锁定AModel表中的相关行,因此不会被其他进程编辑。)

我可以锁定模型BModel

db.session(BModel).query.with_for_update().filter(BModel.id == id).first()

但有可能在一个声明中锁定相关模型AModel吗?或者我是否需要锁定第二条记录,即使我不更新它?

1 个答案:

答案 0 :(得分:1)

如果要一次锁定两个表中的行,请在SELECT ... FOR UPDATE语句中将它们连接起来:

db.session.query(BModel).\
    join(Bmodel.a).\
    with_for_update().\
    filter(BModel.id == id).\
    first()

locking clause上的文档指出,除非使用OF table_name [, ...]命名特定表,否则所有表都会受到影响:

  

如果在锁定子句中命名了特定的表,则只锁定来自这些表的行; SELECT中使用的任何其他表都像往常一样阅读。没有表列表的锁定子句会影响语句中使用的所有表。如果将锁定子句应用于视图或子查询,则会影响视图或子查询中使用的所有表。但是,这些子句不适用于主查询引用的WITH查询。如果要在WITH查询中进行行锁定,请在WITH查询中指定一个锁定子句。

是否需要锁定AModel中的行取决于您正在做什么。如果您不使用AModel的值并且您没有自己更新AModel,那么您可能不需要锁定。