可重复读和串行化两个隔离级别都会产生旨在防止序列化异常的错误。如前所述,使用这些级别的应用程序必须准备好重试因序列化错误而失败的事务。此类错误的错误消息文本会根据具体情况而有所不同,但始终具有 SQLSTATE 代码 40001
(serialization_failure
)。
重试死锁失败也可能是明智的。这些失败具有 SQLSTATE 代码 40P01
(deadlock_detected
)。
在某些情况下,重试唯一键失败(SQLSTATE 代码 23505
(unique_violation
))和排除约束失败(SQLSTATE 代码 23P01
(exclusion_violation
))也是合适的。例如,如果应用程序在检查当前存储的键之后选择主键列的新值,则可能会因另一个应用程序实例同时选择相同的新键而导致唯一键失败。这实际上是序列化失败,但服务器不会将其检测为序列化失败,因为它无法“看到”插入值与先前读取之间的联系。还有一些特殊情况,尽管原则上服务器有足够的信息来确定序列化问题是根本原因,但它仍会发出唯一键或排除约束错误。虽然建议无条件地重试 serialization_failure
错误,但在重试其他错误代码时需要更加谨慎,因为它们可能表示持久的错误状况而不是暂时的故障。
重要的是要重试整个事务,包括决定发出哪些 SQL 和/或使用哪些值的所有逻辑。因此,PostgreSQL 不提供自动重试机制,因为它无法保证正确性。
事务重试不能保证重试的事务会完成;可能需要多次重试。在高度冲突的情况下,事务完成可能需要多次尝试。在涉及冲突的预备事务的情况下,在预备事务提交或回滚之前可能无法取得进展。
如果您在文档中看到任何不正确的内容,与您对特定功能的体验不符,或者需要进一步澄清,请使用 此表单 报告文档问题。