2025年9月25日: PostgreSQL 18 发布!

PostgreSQL 每周新闻 - 2021 年 11 月 28 日

发布于 2021-11-29,作者:PWN
PWN

PostgreSQL 每周新闻 - 2021 年 11 月 28 日

本周人物

11月 PostgreSQL 工作机会

https://archives.postgresql.org/pgsql-jobs/2021-11/

PostgreSQL 本地活动

2022 Nordic PGDay 将于2022年3月22日在芬兰赫尔辛基的希尔顿赫尔辛基斯特兰德酒店举行。论文征集(CfP)将于2021年12月31日截止,请 在此 提交。

PostgreSQL 相关新闻

Planet PostgreSQL:https://planet.postgresql.org/

本周 PostgreSQL 周报由 David Fetter 提供。

请在太平洋标准时间(PST8PDT)周日晚上3:00之前将新闻和公告发送至 david@fetter.org。

已应用补丁

Peter Geoghegan 提交

  • 移除 lazy_scan_heap 并行 VACUUM 的注释块。该注释块不应出现在关于 lazy_scan_heap 执行任务的非常高层次的讨论旁边。在 vacuumlazy.c 的顶部已经有一个类似的、更长的注释块,其中直接提到了 lazy_scan_heap。 https://git.postgresql.org/pg/commitdiff/97f5aef609ce51422934b7dbdba599a7de4dbafd

  • 恢复对标记为 full 的页面的 HOT 考虑。Commit 2fd8685e7f 简化了 heap_update() 中对已修改属性的检查。其中包括了一个微优化,影响了标记为 PD_PAGE_FULL 的页面:为了节省几个周期用于确定 HOT 安全性,甚至不尝试使用 HOT。假设是这次不会成功,因为它上次也不会成功。移除此微优化。它只能节省大部分 heap_update() 调用所消耗的周期,这似乎不值得增加的复杂性。尽管短期内平均节省了一些周期,但对于某些工作负载来说,随着时间的推移,反复应用微优化可能会导致更差的结果。作者:Peter Geoghegan pg@bowt.ie 审阅者:Álvaro Herrera alvherre@alvh.no-ip.org 讨论:https://postgr.es/m/CAH2-WznU1L3+DMPr1F7o2eJBT7=3bAJoY6ZkWABAxNt+-afyTA@mail.gmail.com https://git.postgresql.org/pg/commitdiff/1a6f5a0e876306293fda697e7820b404d5b93693

  • 更新 vacuumlazy.c 的高层次注释。更新 vacuumlazy.c 文件头部的注释(以及 lazy_scan_heap 函数上方的注释),这些注释大部分是在引入 HOT 优化之前编写的,当时 lazy_scan_heap 做的事情少得多,并且在第一次堆扫描时并没有真正进行剪枝。由于 lazy_scan_heap 现在将更多工作外包给了低级函数,因此通过讨论决定每个阶段发生顺序的高层不变量来介绍该函数是有意义的。同时,淡化了我们耗尽 TID 内存的情况,因为推迟讨论这个问题可以更容易地讨论核心问题。最后,移除头部注释中关于并行 VACUUM 的讨论。这些内容并没有太多价值,而且位置不对。 https://git.postgresql.org/pg/commitdiff/12b5ade9023f3ecaddcbc423a22dc284c91c79f6

  • vacuumlazy.c:优先使用“cleanup lock”一词。“super-exclusive lock”是“cleanup lock”的一个可接受的同义词。即使如此,在同一个文件中来回切换术语会引起混淆。在 vacuumlazy.c 中标准化为“cleanup lock”。根据 Andres Freund 的反馈。 https://git.postgresql.org/pg/commitdiff/276db875d4f9be2911582f367596d444d6986c77

Fujii Masao 提交

Peter Eisentraut 提交

Álvaro Herrera 提交

Tom Lane 提交

  • 在检查 TAP 测试所需的模块时,探测 $PROVE 而不是 $PERL。通常,“prove”和“perl”来自同一个 Perl 安装,但我们支持它们不来自同一个安装的情况(主要是因为 MSys 的 buildfarm 机器需要这个)。在这种情况下,AX_PROG_PERL_MODULES 是完全错误的,因为它检查的是“perl”拥有的内容。相反,创建一个包含所需模块的小型 TAP 测试脚本,并在“prove”下运行它。此更改后,我们不再需要 ax_prog_perl_modules.m4,因此将其移除。回溯到所有支持的分支,以方便 buildfarm。 (在 v10 中,这还回溯了 commit 264eb03aa 的效果。)Andrew Dunstan 和 Tom Lane,根据 Noah Misch 的观察。讨论:https://postgr.es/m/E1moZHS-0002Cu-Ei@gemulon.postgresql.org https://git.postgresql.org/pg/commitdiff/c4fe3199a6d65212537a59eb0d7e6fad22b9e903

  • 修复 pg_dump --inserts 模式对带有已删除列的生成列。如果一个表包含一个生成列,该列前面有一个已删除的列,则 dumpTableData_insert 没有考虑已删除的列,并在错误的列中发出 DEFAULT 占位符。这导致还原时失败。默认的 COPY 代码路径没有这个 bug,这可能解释了为什么它没有更早被注意到。在修复此问题时,我们可以更智能地处理这种情况:(1)避免不必要地获取生成列的值,(2)如果我们使用 --column-inserts,也从输出中省略生成列。尽管这些模式的性能预计不如 COPY 路径,但我们也可以尽可能高效;这并没有增加太多复杂性。根据 Дмитрий Иванов 的报告。回溯到 v12(生成列在此版本中引入)。讨论:https://postgr.es/m/CAPL5KHrkBniyQt5e1rafm5DdXvbgiiqfEQEJ9GjtVzN71Jj5pA@mail.gmail.com https://git.postgresql.org/pg/commitdiff/0b126c6a4b00972f2f3533e1718bbe297e2851c2

  • 使 perlcritic 保持安静。根据 buildfarm。 https://git.postgresql.org/pg/commitdiff/db3a660c6327a6df81a55c4aa86e6c0837ecd505

  • 调整 pg_dump 中 cast 的优先级排序。当存储的表达式依赖于用户定义的 cast 时,后端会将依赖记录为对 cast 的实现函数——或者,如果没有涉及 cast 函数,只是 RelabelType 或 CoerceViaIO,则不会记录任何依赖。这对于 pg_dump 来说是问题的,因为其倾倒顺序可能不正确,导致还原失败。鉴于之前没有报告,风险并不高,但如果 cast 用于某个视图,而该视图的行类型随后用作其他函数的输入或结果类型,则可以证明这一点。(这会导致视图被提升到 dump 的函数部分,位于 cast 之前。)一个逻辑上万无一失的修复需要将 cast 的 OID 包含在表达式的解析形式中,然后 dependency.c 可以从中提取,之后存储的依赖关系将强制 pg_dump 做正确的事情。这样的更改将是相当大的入侵,肯定无法回溯。此外,由于我们希望使用 cast 语法的表达式等于(equal())通过显式函数调用做同样事情的表达式,因此 cast OID 字段必须具有特殊的忽略比较语义,这会使事情变得混乱。所以,让我们通过一个非常简单的 hack 来修复 pg_dump:更改对象类型的优先级顺序,使 cast 最初排在函数之前,紧随类型之后。这以一种相当直接的方式修复了没有实现函数的 cast 的问题。对于那些有实现函数的,实现函数将在依赖排序步骤中被提升到 cast 之前,因此我们仍然拥有有效的 dump 顺序。(我不确定这是否能提供完全没有问题的保证;但由于这种情况已经存在很多年了,之前没有任何报告,这可能在实践中足够了。)根据 Дмитрий Иванов 的报告。回溯到所有支持的分支。讨论:https://postgr.es/m/CAPL5KHoGa3uvyKp6z6m48LwCnTsK+LRQ_mcA4uKGfqAVSEjV_A@mail.gmail.com https://git.postgresql.org/pg/commitdiff/b55f2b6926556115155930c4b2d006c173f45e65

  • 文档:改进 nextval()/setval() 的文档说明。澄清 nextval 和 setval 的结果在调用事务提交之前不保证持久。有些人似乎从“这些函数永远不会回滚”的陈述中得出相反的结论,因此重新措辞以避免这样说。讨论:https://postgr.es/m/CAKU4AWohO=NfM-4KiZWvdc+z3c1C9FrUBR6xnReFJ6sfy0i=Lw@mail.gmail.com https://git.postgresql.org/pg/commitdiff/4ac452e2285da347c75f5960ae211e183a87b57b

Michaël Paquier 提交

David Rowley 提交

  • 允许 Memoize 在二进制比较模式下运行。Memoize 始终使用缓存键类型的哈希相等运算符来确定当前参数集是否与之前缓存的某个集合相同。某些类型(如浮点数),其中 -0.0 和 +0.0 在其二进制表示中不同,但被哈希相等运算符视为相等,可能会导致问题,因为除非连接使用相同的运算符,否则有可能正在使用的连接运算符可以区分这两个值。在这种情况下,我们可能会意外地从缓存中返回不正确的行。为了解决这个问题,我们在此添加了一个二进制模式到 Memoize,允许它通过按位比较而不是使用哈希相等运算符来将当前参数集与先前缓存的值进行比较。此二进制模式始终用于 LATERAL 连接,并且当任何连接运算符不可哈希时,它用于普通连接。报告者:Tom Lane 作者:David Rowley 讨论:https://postgr.es/m/3004308.1632952496@sss.pgh.pa.us 回溯到:14(Memoize 添加的版本) https://git.postgresql.org/pg/commitdiff/e502150f7d0be41e3c8784be007fa871a32d8a7f

  • 当非键参数更改时刷新 Memoize 缓存。Memoize 节点下方的子计划可能包含来自 Memoize 节点上方的参数。如果此参数发生更改,缓存条目可能会因新的参数值而过时。以前 Memoize 错误地没有意识到这一点。我们在此通过在任何不是缓存键一部分的参数更改时刷新缓存来修复此问题。Bug:#17213 报告者:Elvis Pranskevichus 作者:David Rowley 讨论:https://postgr.es/m/17213-988ed34b225a2862@postgresql.org 回溯到:14(Memoize 添加的版本) https://git.postgresql.org/pg/commitdiff/1050048a315790a505465bfcceb26eaf8dbc7e2e

  • 撤销“当非键参数更改时刷新 Memoize 缓存”。此操作撤销 commit 1050048a315790a505465bfcceb26eaf8dbc7e2e。 https://git.postgresql.org/pg/commitdiff/dad20ad4709f602b4827a1ab2b0e715f36c548c3

  • 当非键参数更改时刷新 Memoize 缓存,第二版。Memoize 节点下方的子计划可能包含来自 Memoize 节点上方的参数。如果此参数发生更改,缓存条目可能会因新的参数值而过时。以前 Memoize 错误地没有意识到这一点。我们在此通过在任何不是缓存键一部分的参数更改时刷新缓存来修复此问题。Bug:#17213 报告者:Elvis Pranskevichus 作者:David Rowley 讨论:https://postgr.es/m/17213-988ed34b225a2862@postgresql.org 回溯到:14(Memoize 添加的版本) https://git.postgresql.org/pg/commitdiff/411137a429210e432f923264a8e313a9872910ca

Amit Kapila 提交

Robert Haas 提交

  • 修复检测不当时间线切换的边界情况失败。rescanLatestTimeLine() 包含一个保护机制,可以防止切换到从当前时间线在当前恢复点之前分叉的时间线,但如果时间线切换发生在第一个 WAL 记录(必须是检查点记录)被读取之前,该保护机制就不起作用。没有这个补丁,在这种情况下就可能发生不当的时间线切换。这是因为 rescanLatestTimeLine() 依赖于全局变量 EndRecPtr 来了解 WAL 重放的当前位置。然而,此时代码中的 EndRecPtr 存储的是最后一个已重放记录的终点,而不是当前正在重放的记录的起点或终点。因此,在任何记录被重放之前,它是零,这导致健全性检查总是通过。为了解决这个问题,明确地传递正确的时间线。我们想要的 EndRecPtr 值是来自 xlogreader 的值,它将是我们即将尝试读取的记录的起始位置,而不是全局变量,后者是我们成功读取的最后一条记录的结束位置。它们通常是相同的,但在上面描述的边界情况下并非如此。不回溯,因为在 v14 及更早版本的分支中,我们在这里使用了错误 TLI 和错误的 LSN。在 master 中,这由 commit 4a92a1c3d1c361ffb031ed05bf65b801241d7cdd 修复,但它及其先决补丁对于如此小的错误来说过于入侵,无法回溯。作者:我,审阅者:Amul Sul。讨论:http://postgr.es/m/CA+Tgmoao96EuNeSPd+hspRKcsCddu=b1h-QNRuKfY8VmfNQdfg@mail.gmail.com https://git.postgresql.org/pg/commitdiff/e7ea2fa342b008ae97e794b0fa2ee538ddcee3b7

  • xlog.c:移除全局变量 ReadRecPtr 和 EndRecPtr。在大多数地方,这些变量必然存储着 WAL 重放期间使用的 XLogReaderState 的同名成员的值,因为 ReadRecord() 在 XLogReadRecord() 返回后立即将结构成员的值赋给全局变量。然而,XLogBeginRead() 调整了结构成员但没有调整全局变量,因此在 XLogBeginRead() 之后和 XLogReadRecord() 完成之前,值可能不同。否则,它们必须是相同的。根据我的分析,唯一一个变量被引用但可能与其结构成员值不同的地方是 XLogPageRead 中对 EndRecPtr 的引用。因此,在其他所有使用全局变量的地方,我们可以直接切换到使用结构成员,并移除全局变量。然而,我们也可以,而且事实上应该,在 XLogPageRead() 中这样做,因为在该代码点,全局变量将实际存储我们要读取的记录的开始位置——要么是因为它是最后一个 WAL 记录的结束位置,要么是因为在读取最后一个记录后使用了 XLogBeginRead 来更改读取位置。另一方面,结构成员已经被更新为指向我们刚刚读取的记录的末尾。在其他地方,后者是我们传递给 emode_for_corrupt_record() 的参数,所以我们在这里也应该这样做。此补丁部分可能是一个 bug 修复,但我认为它没有重要的后果,所以不回溯。这里的重点是继续减少 xlog.c 中对全局变量的过度使用。讨论:http://postgr.es/m/CA+Tgmoao96EuNeSPd+hspRKcsCddu=b1h-QNRuKfY8VmfNQdfg@mail.gmail.com https://git.postgresql.org/pg/commitdiff/d2ddfa681db27a138acb63c8defa8cc6fa588922

Heikki Linnakangas 提交

Andres Freund 提交

Daniel Gustafsson 提交