处理与SQLAlchemy的事务冲突

时间:2012-07-22 03:34:03

标签: python postgresql concurrency transactions sqlalchemy

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

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

根据我在Google上可以找到的信息,看起来我要么必须获取数据库锁,要么准备重启事务。不幸的是,关于如何实际这一点的信息很少。

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

提前致谢!

- 编辑 -

我刚学会了“ConcurrentModificationError”。这个名字确定听起来就像我正在寻找的例外。 The documentation说它是StaleDataError的别名,它的名字听起来也是正确的,但其文档非常不透明。这是我正在寻找的错误吗?

再次,非常感谢!

2 个答案:

答案 0 :(得分:1)

我从未见过这个错误,虽然StaleModificationError的详细信息表明它可能是您关心的事情,但是不应该锁定整个数据库。您可以阅读transaction isolation in Postgres以防止不同的流程工作者在另一个事务中无意中读取更新行。

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

答案 1 :(得分:1)

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

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

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

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