top语句的PostgreSQL子语句之间的数据一致性如何保证?

How is data consistency guaranteed between PostgreSQL substatements of a top statement?

我仍然无法弄清楚 SQL 语句如何在不干扰彼此工作的情况下并行执行。我大体上了解 ACID 原则,但我很难在特定情况下理解它。例如,在下面的代码片段中,当执行 UPDATE 时,bar.max_count 的值是否不能反映 table foocount 的实际最大值? (例如,如果有人在 table foo 中的 WITH 语句和 UPDATE 语句之间更新或插入新行。

WITH 
  bar AS (
   SELECT id, MAX(count) AS max_count
   FROM foo
   GROUP BY id
  )
UPDATE mytable 
SET count = bar.max_count
FROM bar
WHERE mytable.id = bar.id

换句话说:这个语句会“阻止”其他试图写入 table foo 的并发语句吗?

谢谢

在您更新 mytable 之前,并发语句可能会写入 foo。但是,只要并发语句不也从 mytable 读取,一切都很好,因为这样你的 t运行saction 就可以被认为 逻辑上 早于这些其他的 t运行saction – 就好像你的 t运行saction 运行 首先。

但是如果其中一个并发的 t运行 操作也从 mytable 读取了一个值,如果该信息进入修改 foo,则结果不再需要一致,因为那么您就无法再按逻辑对 t运行 操作进行排序。这被称为 t运行saction 异常,因为如果 t运行saction 一个接一个地执行(序列化),它就永远不会发生。

如果您在默认 READ COMMITTED 隔离级别上操作,您会遇到这种异常情况,该级别提供低级别的 t运行saction 隔离。

为避免此类异常,您必须使用 SERIALIZABLE 隔离级别,保证运行始终获得可序列化的结果。但是存在与 SERIALIZABLE 相关的性能成本,并且通过终止涉及的 t运行 操作之一解决异常 序列化错误 .

另一种方法是悲观锁定,但在您的情况下这会导致过度锁定。