重复读取和可序列化隔离级别都可能产生旨在防止序列化异常的错误。如前所述,
使用这些级别的应用程序必须准备好重新尝试由于序列化错误而失败的事务。
这种错误的消息文本将根据具体情况而变化,但它将始终具有SQLSTATE代码
40001
(serialization_failure
)。
也许值得尝试重新执行死锁失败。这些具有SQLSTATE代码40P01
(deadlock_detected
)。
在某些情况下,重新尝试唯一键失败是合适的,这些失败具有SQLSTATE代码23505
(unique_violation
),以及排除约束失败,这些失败具有SQLSTATE代码23P01
(exclusion_violation
)。例如,如果应用程序在检查当前存储的键后为主键列选择一个新值,
并且在并发情况下另一个应用程序实例选择了相同的新键,则可能会发生唯一键失败。这实际上是一个串行化失败,
但服务器不会将其检测为这样,因为它无法“看到”插入值与先前读取之间的连接。还有一些边缘情况,
在这些情况下,服务器将发出唯一键或排除约束错误,即使原则上它有足够的信息来确定串行化问题是根本原因。
虽然建议无条件重试serialization_failure
错误,但在重试这些其他错误代码时需要更加小心,
因为它们可能代表持久性错误条件而不是瞬态失败。
重试完整的事务非常重要,包括所有决定要发出哪个SQL和/或使用哪些值的逻辑。 因此,PostgreSQL不提供自动重试功能,因为无法保证正确性。
事务重试并不保证重试的事务会完成;可能需要多次重试。在存在非常高的争用情况下, 完成事务可能需要多次尝试。在涉及冲突的已准备事务的情况下,可能无法取得进展, 直到已准备事务提交或回滚。