我正在访问带有序列化事务隔离的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
。显然,以这种方式旋转以避免序列化争用是不合适的?我应该以不同的方式做这件事吗?
一些注意事项:我正在使用不同的进程访问表(这些进程完全相同并执行相同的操作:选择,递增和更新/插入表中。)每个进程都有自己的连接{{1他们没有共享连接。
另一个注意事项:似乎在经过conn
异常块之后,在while循环的下一次旋转中,它最终会在TransactionRollbackError
异常块中结束。
还有一点需要注意:同时运行的进程数直接影响错误的频率,因为更多进程往往会产生更多错误。所以有一些争论正在进行中。我的印象是使用带有重试的序列化事务隔离(如我的演示代码中)将解决此问题。
答案 0 :(得分:4)
您应该在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。
请注意,除非您一直在进行自己的事务控制或以autocommit
模式建立连接,否则它将回滚所有 SQL命令。