【问题标题】:Is it possible to have different results in CTE clauses in READ COMMITTED isolation level?READ COMMITTED 隔离级别的 CTE 子句是否可能有不同的结果?
【发布时间】:2017-12-31 09:24:54
【问题描述】:

read committed 隔离级别中,同一事务中的两个后续选择查询可能会产生不同的结果,因为这两个查询之间可能存在并发更新:

transaction 1: select id from table;
    => returns [1, 2, 3]
transaction 2: delete from table where id = 2;
transaction 1: select id from table;
    => returns [1, 3]

如果事务 1 中的选择查询合并到 CTE 中会发生什么?假设我有以下虚拟查询:

with
cte_1 as (select id from table),
cte_2 as (select id from table)
select (select count(*) from cte_1, select count(*) from cte_2)

如果在cte_1cte_2 的执行之间发生并发更新,现在是否也有可能得到不同的结果?

【问题讨论】:

    标签: sql postgresql


    【解决方案1】:

    每个语句都以原子方式执行,并且在整个运行时都会看到数据库的一致视图。 “两个 CTE”是一个单个查询,因此查询在运行时也看不到任何(已提交的)更改

    CTE 查询等价于:

    select (select count(*) from (select id from table) as cte1), 
           (select count(*) from (select id from table) as cte2)
    

    无关,但是:您可能不知道 select (a,b) 在 Postgres 中与 select a,b 不同。第一个返回具有匿名记录类型的单列(具有两个字段),第二个返回两列。

    【讨论】:

    • 谢谢,很有趣!还有关于(a, b)a, b 的评论,我在写问题时并没有真正意识到这一点。
    • “这两个 CTE 是一个查询,因此查询在运行时也看不到任何(已提交的)更改。”我已经在 SO 上的几个地方看到了这种说法,但我无法找到证实它的权威来源(如 PostgreSQL 手册中的部分或句子)。有什么指点吗?
    • @AndresRiofrio: Quote from the manual "当事务使用此隔离级别时,SELECT 查询 (...) 只会看到在查询开始之前提交的数据;它永远不会看到未提交的数据或并发事务在查询执行期间提交的更改"
    • @a_horse_with_no_name 是的,但这并不能真正说明这意味着每个 root SELECT 查询还是每个 SELECT 查询,甚至是子查询。事实上,它对我来说似乎意味着后者。
    • 一条语句就是一条语句。
    猜你喜欢
    • 2019-06-18
    • 2010-11-30
    • 2011-04-22
    • 1970-01-01
    • 2014-09-18
    • 1970-01-01
    • 2012-07-04
    • 2021-01-30
    • 1970-01-01
    相关资源
    最近更新 更多