正确使用 psycopg2 序列化

Proper use of serialization with psycopg2

我正在访问带有序列化事务隔离的 postgresql table。我正在做这样的事情(使用现有的 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。显然,以这种方式旋转以避免序列化争用是不合适的?我应该换一种方式吗?

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

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

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

您应该在 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

请注意,它将回滚 all 迄今为止的 SQL 命令,除非您一直在进行自己的事务控制或在 autocommit 模式下建立连接.