【问题标题】:Why rows get changeg after UPDATE in table? PostreSQL [duplicate]为什么在表中更新后行会更改? PostgreSQL [重复]
【发布时间】:2021-06-10 22:06:36
【问题描述】:

我的初始表

更新版本后的表 select * from "table";

【问题讨论】:

  • 我自己并不是真正的 PostgreSQL 人,但通常在表上应用的任何主键/默认索引都将确定行的排序顺序(如果您不包含任何特定的 ORDER BY您的 SELECT 语句)。在这种情况下,我的猜测是“版本”列是这个特定表的默认排序顺序中的一个因素
  • 至少让每个人都知道您所做的更新会很有用。使用select * from "table" 更新版本并不像您想象的那样一目了然。
  • 行被改变是因为更新改变了一些行的内容。你到底是什么意思?
  • 我相信 OP 所问的具体问题是,“为什么在更新 ID = 3 的行的版本号后,行出现的顺序是什么(做一个简单的 SELECT * FROM 表)改变?”
  • @craig。默认情况下,行是无序的,PK/indexing 不会进入其中。如果您想要 ORDER,您需要使用 ORDER BY 指定它。

标签: sql postgresql


【解决方案1】:

作为正式定义,关系 DBMS 是建立在关系代数之上的,关系代数是在集合论领域中运行的数学分支...

在数学集合中,绝对没有默认顺序,因为集合是“包”,而包中的物品在旅行时会“混合”……(去看看你女朋友钱包里的东西说服自己吧!)

这就是为什么在 SQL SELECT 语句中有一个 ORDER BY 子句的原因,因为 RDBMS 永远无法确保任何顺序都会得到尊重!而且返回的行的位置可以随时改变!

【讨论】:

  • 很确定,他一直在使用堆表。在这种情况下,更新导致第 3 行由于重写而移出堆的末尾。
  • @TarekSalha:即使 Postgres 确实有除了“堆表”(即聚集索引)之外的其他东西,它仍然不能保证没有order by 的特定排序顺序(想想并行执行或同步 seq 扫描)
  • @a_horse_with_no_name 你是对的......即使在像 Microsoft SQL Server 这样的聚集索引中,也没有默认的常量排序。因为引擎在多线程中执行此操作,所以一个任意线程将首先完成,最后一个完成,每次执行时很少相同......所以最终的连接结果将具有任意顺序。还有许多其他情况会产生相同的行为。
  • @Tarek_Salha 是的,因为 PostGreSQL 执行 UPDATE 的唯一方法是系统地创建一个新行。这种“奇怪”的 PG 行为是由于 MVCC 的错误实现造成的。请参阅我关于这些问题的论文...mssqlserver.fr/…
【解决方案2】:

行顺序改变的原因是PostgreSQL的多版本实现。

当在 PostgreSQL 中更新一行时,实际的表条目(“元组”,使用术语)不会被修改。而是将新版本的行插入到表中,旧版本被标记为无效(我在这里简化)。并发读者仍然可以访问旧的元组来获取原始数据。当没有人需要旧的元组时,它会被 autovacuum 回收。

在您的情况下,新元组已添加到表的末尾。因此,如果看起来UPDATE 移动了一行,那是因为这就是实际发生的情况。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2015-12-16
    • 2022-01-05
    • 1970-01-01
    • 2021-08-27
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多