【问题标题】:postgres 9.5 row level locks concurrency exceptionpostgres 9.5 行级锁并发异常
【发布时间】:2017-03-22 18:34:48
【问题描述】:

我最近遇到了 postgres 并发错误,在此不再赘述。原始帖子可以在this link 找到。

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

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

【问题讨论】:

  • 为什么不将你的发现发送到 postgres 邮件列表?在那里您可以找到真正的专家以及最初编写代码的专家。 postgresql.org/list
  • “我有一个存储过程,它读取一个表,然后根据读取的输出插入。” 它是否“读取一个表”来确定是一行还是行存在吗?它读了多少表?
  • 没有。事实上,读取跨越 3 个表需要一个中间联合/计数。这不是检查行是否存在并在不存在时插入的简单情况。这可以通过 inserton conflict 子句来处理。读取本身有一个涉及的WHERE 子句,它将自动限制读取将触及的行数。

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


【解决方案1】:

首先,您在提供的链接中遇到的不是错误,而是预期和记录的行为。

我了解到您正在使用事务隔离级别 SERIALIZABLE

在这种模式下,您读取的每一行都被一个特殊的SIReadLock 锁定,它不会阻塞任何东西,但用于确定是否可能发生了序列化异常,在这种情况下,事务会因序列化错误而中断.

请注意,不仅返回给您的行以这种方式被锁定,而且在执行查询期间访问的所有表中的所有行都被锁定。因此,如果您的执行计划中有顺序扫描,则表的所有行将有一个SIReadLock。此外,如果表上的此类锁过多,它们会升级为页级或表级锁。

因此可能会不必要地锁定行。除此之外,用于检测不一致的算法可能会报告误报(准确地说,计算成本太高)。

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

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

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2016-10-01
    • 1970-01-01
    • 2018-03-04
    • 1970-01-01
    • 2016-12-20
    • 1970-01-01
    • 2018-09-10
    相关资源
    最近更新 更多