【发布时间】: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 异常块。
还有一点需要注意:同时运行的进程数对错误频率有直接影响,因为更多的进程往往会产生更多的错误。因此,存在某种争论。我的印象是使用带有重试的序列化事务隔离(如在我的演示代码中)可以解决此问题。
【问题讨论】:
-
你在
rollbackthe connection 在except TransactionRollbackError分支吗? -
@musically_ut - 我没有,我认为我不应该。我错了吗?
-
conn.rollback()是我在cur.execute的论点中犯错后从错误中恢复以继续使用光标的方式。粗略阅读错误消息表明事务也应该中止,this post 建议做类似的事情。为什么你认为你不应该回滚? -
@musically_ut - 我的(可能是愚蠢的)假设是,由于它是由于序列化争用而导致的错误,我可以简单地重试而不回滚。我将尝试创建一个保存点并回滚/恢复。
-
您不需要显式创建保存点。每个独立的
execute都在一个事务中运行,如果语句遇到问题,您的连接就会陷入该事务。只需在正确的分支中执行conn.rollback()就足够了。
标签: python postgresql psycopg