【问题标题】:Handling transaction conflict with SQLAlchemy使用 SQLAlchemy 处理事务冲突
【发布时间】:2012-07-20 19:22:27
【问题描述】:

我对数据库比较陌生。我确信这是经验会回答的问题。

我将 SQLAlchemy 与 PostgreSQL 一起使用。我设置了一个系统,其中分布在多台计算机上的多个进程执行各种任务,然后更新数据库。我在测试中还没有遇到任何事务冲突,但理论上它们仍然是可能的。

根据我在 Google 上找到的信息,看来我要么必须获得数据库锁,要么准备重新启动事务。不幸的是,关于如何执行此操作的宝贵信息很少。

我假设,要重新启动事务,SQLAlchemy 会抛出一些异常,我的代码必须捕获该异常,并自行执行重试。如果我违反了唯一性约束,表明我的代码中存在错误而不是事务冲突,那么该异常是否与 SQLA 抛出的异常不同?使用数据库锁会更好吗?

提前致谢!

-- 编辑--

我刚刚了解了“ConcurrentModificationError”。这个名字确实听起来像我正在寻找的例外。 The documentation 说它是 StaleDataError 的别名,它的名字听起来还是对的,但它的文档非常不透明。这是我要查找的错误吗?

再次,非常感谢!

【问题讨论】:

    标签: python postgresql concurrency transactions sqlalchemy


    【解决方案1】:

    只是在 khoxsey 的回答中添加一些细节。

    如果并发事务相互干扰,将事务隔离级别设置为“可序列化”将使 PostgreSQL 引发错误。当有许多并发数据库连接时,“可序列化”隔离级别会降低性能,但在我的情况下,性能不是问题的足够少。

    当事务在此序列化级别上相互冲突时,Postgres 将其称为“序列化错误”,其 SQLSTATE error code 为“40001”。当前没有驱动程序可移植的方式来访问 SQLAlchemy 中的 SQLSTATE。但是,当使用 psycopg2 驱动程序时,可以通过 exc.orig.pgcode 访问 SQLSTATE 代码,其中 exc 是由 except 捕获的异常声明。

    据我所知,异常本身应该是 OperationalError。

    【讨论】:

      【解决方案2】:

      我从未见过那个错误,虽然StaleModificationError 的详细信息表明它可能是您关心的问题,但应该没有必要锁定整个数据库。您可以阅读 transaction isolation in Postgres 以防止不同的流程工作人员在不知情的情况下读取另一个事务中正在更新的行。

      如果您将隔离级别设置得更高(已提交读等),那么您的 SA 会话将开始在它所接触的各个行上收集锁。您决定为您的设计设置隔离级别的严格程度。你可以让它足够严格,这样你的读者在尝试读取另一个事务锁定的行时会抛出异常,然后你可以选择回滚或使用refresh/expire interface 来更新该特定会话。

      【讨论】:

        猜你喜欢
        • 2013-06-20
        • 2010-12-29
        • 2022-08-11
        • 1970-01-01
        • 2016-06-30
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多