SERIALIZATION FAILURE(40001)

时间:2013-10-01 16:03:29

标签: postgresql isolation-level

我已经知道,如果序列化失败,应该重新执行可序列化级别的事务。

我只是对2个scenarii感到好奇,其中引发了40001错误:

  1. 运行INSERT命令时。
  2. 发出准备交易声明时。
  3. 在每种情况下,序列化问题的根本原因是什么? 您对这些特殊情况的体验是什么?

    我想通过查看并发事务来尝试减少这些问题。

    TIA。

    更新1

    PostgreSQL wiki我了解到,在可序列化的事务中,第一个COMMIT获胜。 PREPARE似乎表现得像COMMIT,所以我可以理解它为什么会失败。

    但是,对于INSERT情况,如果没有执行SELECT的并发可序列化事务,我就错过了这一点。从我到目前为止看到的只有多个并发INSERT。

    更新2

    我发现我在同一张桌子上有并发SELECT ... FOR SHARE。

    更新3

    这里似乎有一种模式,当交易失败时,交易的持续时间比往常更长。这是因为我们正在处理文件,这可能需要比预期更长的时间。我会尝试通过重新安排各种任务来减少交易的持续时间。

1 个答案:

答案 0 :(得分:2)

文档对40001如何发生进行了相当好的讨论:

http://www.postgresql.org/docs/current/static/transaction-iso.html

引用,而不是详细解释,适用的dos和donts:

  

为了完整性目的,不要将更多内容放入单个事务中。

     

不要让悬挂在“交易中闲置”的连接超过必要的时间。

     

当系统被强制将多个页级谓词锁组合成单个关系级谓词锁时,因为谓词锁表缺少内存,可能会导致序列化失败率增加。您可以通过增加max_pred_locks_per_transaction来避免这种情况。

     

顺序扫描总是需要关系级谓词锁定。这可能导致序列化失败率增加。通过减少random_page_cost和/或增加cpu_tuple_cost来鼓励使用索引扫描可能会有所帮助。请务必权衡事务回滚的任何减少,并重新启动查询执行时间的任何整体更改。

换句话说,在写作时尽快提交,并避免在整个地方读取或写入大量查询。