postgres 9.5行级锁定并发异常

时间:2017-03-22 18:34:48

标签: database postgresql stored-procedures concurrency postgresql-9.5

我最近遇到了postgres并发错误,我在这里不再重复。原帖可以在this link找到。

我仍然在努力更好地理解postgres如何处理可序列化的并发性。我的情况是这样的。我有一个存储过程,它读取一个表,然后根据读取的输出插入。如果多个客户端调用此存储过程,则会导致40001读/写依赖性异常。

问题是这个。让我们假设读取表然后根据读取插入表的存储过程只读取一些行。如果保证每次对read-insert的存储过程的调用都会触及不同的行,那么并发异常会消失吗? postgres是否足够智能以跟踪在事务期间读取哪些行,以便它可以准确地检测由不同事务修改那些特定行,从而导致异常?如果是的话,这种机制有多可靠?在某些情况下可以对它进行优化吗和postgres,为了安全起见,在修改任何读表时抛出异常?

1 个答案:

答案 0 :(得分:0)

首先,您在链接中遇到的是错误,但是有意和记录的行为。

我认为您正在使用事务隔离级别SERIALIZABLE

在此模式下,您读取的每一行都被一个特殊的SIReadLock锁定,该特殊SIReadLock不阻止任何内容,但用于确定是否可能发生序列化异常,在这种情况下事务被中断序列化错误。

请注意,不仅以这种方式锁定返回给您的行,而且还会在执行查询期间访问所有表中的所有行。因此,如果执行计划中存在顺序扫描,则该表的所有行将具有SERIALIZABLE。此外,如果表上有太多这些锁,它们会升级到页级或表级锁。

因此可能会不必要地锁定行。除此之外,用于检测不一致性的算法可以报告误报(计算上的确太昂贵)。

因此,可能在您描述的情况下接收序列化错误,尽管只要一切都保持简单并且没有顺序扫描,我就不会发现任何错误。

序列化错误是正常的,可以在std::vector::emplace_back隔离级别上预期。您的应用程序必须准备好通过重试事务来处理它们。这是您不必担心数据一致性而需要付出的代价。