【问题标题】:SQLAlchemy long running script: User was holding a relation lock for too longSQLAlchemy 长时间运行脚本:用户持有关系锁的时间过长
【发布时间】:2015-07-17 19:58:42
【问题描述】:

我在脚本中有一个 SQLAlchemy 会话。该脚本运行了很长时间,它只从数据库中获取数据,从不更新或插入。

我遇到了很多错误,例如

sqlalchemy.exc.DBAPIError: (TransactionRollbackError) terminating connection due to conflict with recovery
DETAIL:  User was holding a relation lock for too long.

按照我的理解,SQLAlchemy 创建一个事务,第一个选择发出,然后重用它。由于我的脚本可能会运行大约一个小时,因此很可能在该事务的生命周期内出现冲突。

为了消除错误,我可以在不推荐使用的模式下使用自动提交(不做任何其他事情),但文档明确不鼓励这样做。

处理错误的正确方法是什么?我可以在没有事务的情况下使用 ORM 查询吗?

【问题讨论】:

  • 通常这类问题是通过将工作分批处理来处理的。例如。在每 1000 个对象之后提交/回滚以向数据库发出信号,您已完成数据处理,并且您不在乎内容是否更改。所以这听起来更像是脚本设计本身可以改进。
  • 您始终可以使 SQLAlchemy 对象可重用,即使在使用选项关闭事务后,也可以在内存中复制数据。
  • 您是否将它与流复制一起运行?..
  • @BartoszMarcinkowski 所以这是错误的根源。 “增加 max_standby_archive_delay 和 max_standby_streaming_delay 将有助于完成查询。有关详细信息,请参阅以下手册。” (c) 阅读postgresql.org/docs/9.0/interactive/…
  • 很遗憾,我无法更改 PostgreSQL 配置;我需要我的脚本来处理当前的复制设置。

标签: python postgresql session transactions sqlalchemy


【解决方案1】:

我在(几乎)每次选择之后都关闭了会话,比如

session.query(Foo).all()
session.close()

由于我不使用自动提交,因此会自动打开一个新事务。

【讨论】:

  • 这是正确的做法。无论发送什么查询,事务都会开始。所以即使你只从数据库中读取,你也需要提交/关闭它。
猜你喜欢
  • 2018-07-02
  • 2019-02-12
  • 2013-05-12
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多