【问题标题】:Proper use of serialization with psycopg2正确使用 psycopg2 的序列化
【发布时间】:2015-10-24 05:19:15
【问题描述】:

我正在访问具有序列化事务隔离的 postgresql 表。我正在做这样的事情(现有的 psycopg2 连接 conn 和该连接中的光标 cur:

while True:
  try:
    cur.execute(query)
    break
  except TransactionRollbackError:
    [sleep a little]
    continue
  except Exception:
    [handle error here]

这样做的目的是在发生序列化争用时重试。现在,这在很多时候都可以正常工作。但在TransactionRollbackError 陷阱中进行一次迭代后,我经常会收到此错误:

current transaction is aborted, commands ignored until end of transaction block。显然,以这种方式旋转以避免序列化争用是不合适的?我应该以不同的方式来做这件事吗?

一些注意事项:我正在使用不同的进程访问表(它们都是相同的并且做同样的事情:选择、递增和更新/插入到表中。)这些进程中的每一个都有自己的连接conn ,他们不共享连接。

另一个注意事项:似乎在经历了一次 TransactionRollbackError 异常块之后,在 while 循环的下一次旋转中,它最终进入了 Exception 异常块。

还有一点需要注意:同时运行的进程数对错误频率有直接影响,因为更多的进程往往会产生更多的错误。因此,存在某种争论。我的印象是使用带有重试的序列化事务隔离(如在我的演示代码中)可以解决此问题。

【问题讨论】:

  • 你在rollback the connectionexcept TransactionRollbackError 分支吗?
  • @musically_ut - 我没有,我认为我不应该。我错了吗?
  • conn.rollback() 是我在cur.execute 的论点中犯错后从错误中恢复以继续使用光标的方式。粗略阅读错误消息表明事务也应该中止,this post 建议做类似的事情。为什么你认为你不应该回滚?
  • @musically_ut - 我的(可能是愚蠢的)假设是,由于它是由于序列化争用而导致的错误,我可以简单地重试而不回滚。我将尝试创建一个保存点并回滚/恢复。
  • 您不需要显式创建保存点。每个独立的execute 都在一个事务中运行,如果语句遇到问题,您的连接就会陷入该事务。只需在正确的分支中执行 conn.rollback() 就足够了。

标签: python postgresql psycopg


【解决方案1】:

您应该在except TransactionError: 分支中执行rollback 以从错误状态中恢复:

while True:
  try:
    cur.execute(query)
    break
  except TransactionRollbackError:
    conn.rollback()
    [sleep a little]
    continue
  except Exception:
    [handle error here]

这是recommendation made the FAQ as well

请注意,它将回滚所有到目前为止的 SQL 命令,除非您一直在进行自己的事务控制或在autocommit 模式下连接。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-08-16
    • 2022-12-12
    • 1970-01-01
    相关资源
    最近更新 更多