“count(*)”是否能保证在任何交易级别的交易中返回相同的结果?

Eva*_*oll 4 postgresql concurrency transaction locking mvcc

如果我创建一个表。

CREATE TABLE foo AS
SELECT CASE WHEN random() > 0.5 THEN x END AS x
FROM generate_series(1,10) AS x;
Run Code Online (Sandbox Code Playgroud)

然后我在事务中运行以下命令

BEGIN;
  SELECT count(*)
  FROM foo
  WHERE x IS NOT NULL;

  --time

  SELECT count(*)
  FROM foo
  WHERE x IS NOT NULL;
END;
Run Code Online (Sandbox Code Playgroud)

在什么交易级别下我的结果保证在交易中保持不变?

joa*_*olo 5

我的十美分,基于PostgreSQL 文档

假设:您自己的事务不会更改foo中的任何相关值。

count(*)在两个查询中具有相同的含义意味着:

  1. 您不能拥有,因为另一个事务可能在第一个和第二个 select 之间dirty reads将更多行写入您的foo表中;你不应该看到他们。

  2. 您并没有真正阅读任何专栏,所以这nonrepeatable reads不是问题。

  3. 您不能拥有phantom reads,也就是说,如果另一个事务将其x列为NULL非空值的任何行更改,您的事务不必注意到这些影响条件的更改WHERE

  4. 我实在不知道该如何判断serialization anomalies。我的有根据的猜测是这不是必需的。但这确实是非常有争议的

在这些条件下,事务隔离级别表明确表明Repeatable read符合以下标准:

  1. 没有脏读
  2. 没有不可重复读取
  3. 没有幻读(在 PostgreSQL 中,但标准不要求)

...因此,它会count(*)在两个 select 语句中为您提供相同的结果。