可重复读和可串行化隔离级别都可能产生旨在防止串行化异常的错误。 如前所述,使用这些级别的应用必须准备好重试因串行化错误而失败的事务。 这类错误的消息文本会随具体情况而变化,但其 SQLSTATE 代码始终是 40001(serialization_failure)。
重试因死锁而失败的事务也可能是明智的。这类错误的 SQLSTATE 代码为 40P01(deadlock_detected)。
在某些情况下,重试唯一键违例也是合适的,这类错误的 SQLSTATE 代码为 23505(unique_violation);重试排除约束违例也可能合适, 其 SQLSTATE 代码为 23P01(exclusion_violation)。 例如,如果应用在检查当前已存储键值之后,为主键列选择了一个新值, 那么另一个应用实例并发选择了同一个新键时,就可能发生唯一键违例。 这实际上是一种串行化失败,但服务器不会把它识别为此类错误, 因为它无法“看到”插入值与先前读取之间的联系。 还有一些边缘情况,在这些情况下,即使原则上服务器拥有足够的信息来判断根本原因是串行化问题, 它也仍会报出唯一键或排除约束错误。虽然建议无条件重试 serialization_failure 错误,但在重试这些其他错误代码时需要更加谨慎, 因为它们可能代表持久性错误,而不是瞬态失败。
重试完整事务非常重要,其中应包括决定发出哪些 SQL 和/或使用哪些值的全部逻辑。 因此,PostgreSQL 不提供自动重试功能,因为它无法在正确性上作出保证。
重试事务并不保证重试后的事务一定能够完成;可能需要多次重试。 在争用非常激烈的情况下,完成一个事务可能需要尝试很多次。 如果涉及相互冲突的已准备事务,那么在已准备事务提交或回滚之前,可能根本无法取得进展。
如果您发现文档中有不正确的内容、与您使用特定功能的经验不符或需要进一步说明,请使用此表单来报告文档问题。