【发布时间】:2017-09-14 08:59:19
【问题描述】:
我想知道是否有可能以某种方式锁定几个数据库表以进行受保护的写入或类似的事情,以防止另一个应用程序在事务进行时修改这些表?
我现在有这样的东西。表 A、B 和 C,它们之间存在一对多关系 A->B 和 B->C。此函数从 rabbitmq 接收数据并更新 A、B 和/或 C(通常只有 C)或在缺失时创建新行。
Session=scoped_session(session_factory)
try:
foo = Session.query(A).filter(....).one()
except NoResultFound:
Session.remove()
return
try:
bar = Session.query(B).filter(......).one()
except NoResultFound:
bar = B(field1=x, field2=y etc.)
Session.add(bar)
try:
xyzzy = Session.query(C).filter(...).order_by(...).limit(1).one()
except NoResultFound:
xyzzy = C(.......)
Session.add(xyzzy)
foo.fieldn = var1
bar.fieldn = var2
xyzzy.fieldn = var3
etc.
Session.commit()
Session.remove()
这一切都很好。问题是,我有另一个程序(完全不同的 python 脚本)可以根据请求进行清理。它基本上删除了 A、B 和 C 中的所有内容。这也有效。
我的第一个程序在删除后立即崩溃:
sqlalchemy.orm.exc.StaleDataError: UPDATE statement
on table 'C' expected to update 1 row(s); 0 were matched.
我可以捕捉到这个异常并做出相应的反应,但我需要这样做吗?如果我可以在两个程序中为短文件保留 database 级别的 A、B 和 C,则此问题将得到解决。所有这些交易的持续时间都很短。我从 sqlalchemy 文档中了解到,会话也应该启动事务,但显然这意味着与数据库级别的事务不同。
似乎发生的事情是我的 Session.query(C) 找到了一行,但在第一个程序发出 Session.commit() 之前,另一个程序已将其删除。
20 多年前,在 90 年代的数据库和 C 中,我总是使用 DECLARE TRANSACTION ... 为受保护的写入保留 A、B、C;或类似的东西。现在已经消失了,我只需要捕获异常,还是我仍然可以从数据库级别的锁定中受益?
汉努
【问题讨论】:
标签: python postgresql transactions sqlalchemy