在 Postgres 中组合依赖于不同事务隔离级别的代码

Combining code that relies on different transaction isolation levels in Postgres

我有两个函数都需要一个 t运行saction。一个在呼唤另一个。我有代码可以使用 SAVEPOINT 将这样的 t运行sactions 嵌套到一个中。

如果它们具有相同的 t运行saction 隔离级别,则没有问题。现在,如果他们不这样做,我还有办法 'correctly' 结合 t运行 行动吗?

如果我 运行 在两者中最严格的隔离级别下 运行saction,除了性能下降之外,会有什么风险?

在这种情况下,是的,通常您可以将事务合并到更严格的隔离级别中。

风险在于更高的隔离级别会捕捉到更多的序列化错误(即 REPEATABLE READ 中的 ERROR: could not serialize access due to concurrent update 和 SERIALIZABLE 中的 ERROR: could not serialize access due to read/write dependencies among transactions)。处理这些序列化失败的典型方法是重试事务,但您应该验证这在您的应用程序上下文中是否有意义。

另一个可能出现的错误是死锁。 Postgres 应该检测到这些并打破死锁(之后失败的事务应该重试),但是如果可以的话,您应该始终尝试编写您的应用程序,以便首先不存在死锁。通常,避免死锁的主要技术是确保所有获取任何锁(隐式或显式锁)的应用程序以一致的顺序获取这些锁。

如果您的应用程序需要向其他外部服务发出请求,您可能需要特别小心,因为您可能需要验证重试是否会导致您发出不需要的重复请求,尤其是如果这些外部请求是不是幂等的。