top语句的PostgreSQL子语句之间的数据一致性如何保证?
How is data consistency guaranteed between PostgreSQL substatements of a top statement?
我仍然无法弄清楚 SQL 语句如何在不干扰彼此工作的情况下并行执行。我大体上了解 ACID 原则,但我很难在特定情况下理解它。例如,在下面的代码片段中,当执行 UPDATE
时,bar.max_count
的值是否不能反映 table foo
中 count
的实际最大值? (例如,如果有人在 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运行 操作之一解决异常 序列化错误 .
另一种方法是悲观锁定,但在您的情况下这会导致过度锁定。
我仍然无法弄清楚 SQL 语句如何在不干扰彼此工作的情况下并行执行。我大体上了解 ACID 原则,但我很难在特定情况下理解它。例如,在下面的代码片段中,当执行 UPDATE
时,bar.max_count
的值是否不能反映 table foo
中 count
的实际最大值? (例如,如果有人在 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运行 操作之一解决异常 序列化错误 .
另一种方法是悲观锁定,但在您的情况下这会导致过度锁定。