5

我正在使用序列化事务隔离访问一个 postgresql 表。我正在做这样的事情(conn在该连接中使用现有的 psycopg2 连接和光标,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异常块。

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

4

1 回答 1

5

您应该rollbackexcept TransactionError:分支中执行 a 从错误状态中恢复:

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

这也是常见问题解答中的建议

请注意,它将回滚迄今为止的所有autocommitSQL 命令,除非您一直在进行自己的事务控制或处于模式下的连接。

于 2015-08-01T19:45:19.817 回答