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

PostgreSQL 周报 - 2021 年 4 月 18 日

发布于 2021-04-19, 作者 PWN
PWN

PostgreSQL 周报 - 2021 年 4 月 18 日

本周人物:https://postgresql.life/post/devrim_gunduz/

PostgreSQL 产品新闻

pgmetrics 1.11 发布,这是一个用于 PostgreSQL 指标的命令行工具。https://pgmetrics.io/

hypopg 1.2.0 发布,这是一个实现了假索引的扩展。https://github.com/HypoPG/hypopg/releases

四月 PostgreSQL 工作机会

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

PostgreSQL 相关新闻

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

本周 PostgreSQL 周报由 David Fetter 提供。

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

已应用补丁

Tom Lane 提交

  • 抑制一些 Coverity 警告并改进代码一致性。Coverity 报告了类似 intresult = tm->tm_sec * 1000000 + fsec 这样的表达式中可能发生的溢出,理由是乘法会在 32 位算术中发生,然后才能扩展到 int64 结果。我认为这些都是误报,因为 tm_sec 的可能范围有限;但即使如此,当附近行具有相同的计算方式但使用 64 位常量时,这样写看起来仍然很愚蠢。……或者更准确地说,是使用 LL 常量,但这不符合项目风格。像我们其他地方一样,将所有这些都使用 INT64CONST()。这是来自 a2da77cdb 的新代码,因此无需回填。https://git.postgresql.org/pg/commitdiff/6277435a8a89c59f716c111200c072d1454b8ff2

  • 修复了将 COLLATE 表达式的结果强制转换的旧错误。parse_coerce.c 中有一些技巧可以将请求的强制转换推送到可能出现的 CollateExpr 的下方。然而,即使请求的数据类型是不可排序的,我们也会这样做,导致生成一个无效的表达式树,其中 CollateExpr 应用于不可排序的类型。修复方法是直接删除 CollateExpr,理由是它没有用。这个错误已有十年历史,可追溯到 COLLATE 支持的最初添加。缺乏报告表明,对用户可见的影响并不多。我们注意到这个问题是因为它会在 DefineVirtualRelation 中触发断言,如果无效结构出现在视图的输出列中;然而,在非断言构建中,你不会看到崩溃,只是关于将排序应用于不可排序类型的(微妙不正确的)抱怨。我发现通过将不正确的结构进一步放入视图中,可以创建一个失败转储/重新加载的视图定义,如添加的回归测试用例所示。但 CollateExpr 在运行时不起作用,所以这可能不会导致任何真正令人兴奋的后果。根据 Yulin Pei 的报告。回填到所有支持的分支。讨论:https://postgr.es/m/HK0PR01MB22744393C474D503E16C8509F4709@HK0PR01MB2274.apcprd01.prod.exchangelabs.com https://git.postgresql.org/pg/commitdiff/c402b02b9fb53aee2a26876de90a8f95f9a9be92

  • 删除不再相关的测试用例。collate.icu.utf8.sql 曾经测试了为枚举比较表达式记录排序依赖项,但实际上这样的表达式不应该有任何排序依赖项。在我修复了 commit c402b02b9 之后,该测试开始失败。我们不再需要测试这种情况,所以只需删除现在无用的测试步骤。(此测试用例在 HEAD 中是新添加的,因此无需回填。)讨论:https://postgr.es/m/3044030.1618261159@sss.pgh.pa.us 讨论:https://postgr.es/m/HK0PR01MB22744393C474D503E16C8509F4709@HK0PR01MB2274.apcprd01.prod.exchangelabs.com https://git.postgresql.org/pg/commitdiff/cf0020080a3de20287217621da57bfd840e9a693

  • 避免 heap_update 中出现罕见的 PANIC。heap_update 需要清除旧元组页上(以及新页上,如果不同)任何现有的“全部可见”标志。根据编码规则,要做到这一点,它必须在不持有独占缓冲区锁的情况下锁定相应的可见性映射页;这会产生竞争条件,因为只要我们不持有缓冲区锁,其他人就可以设置该标志。代码应该通过在获取缓冲区锁后重新检查标志并重试(如果已设置)来处理。然而,heap_update 本身的一个代码路径,以及其子程序 RelationGetBufferForTuple 的一个代码路径,未能做到这一点。最终结果是,在一个并发 VACUUM 在我们临时不持有锁时设置了该标志的罕见事件中,会出现一个非周期性的“PANIC: wrong buffer passed to visibilitymap_clear”故障。自最近的 VACUUM 更改以来,这在构建农场中已出现几次,这些更改添加了可以在仅持有独占缓冲区锁的情况下设置所有可见标志的代码路径。以前,该标志(通常?)仅在执行 LockBufferForCleanup 后设置,后者会强制要求缓冲区引用计数为零,从而阻止在 heap_update 的中间设置该标志。然而,很明显,问题出在 heap_update 而不是 VACUUM。不太清楚的是,这些错误在已发布的版本中是否存在任何危险。heap_update 肯定违反了 API 预期,但如果没有代码路径可以在没有清理锁的情况下设置所有可见项,那么这只是一个潜在的错误。但这并非 100% 确定,而且我们还应该担心扩展程序或未来的回填修复可能引入此类代码路径。我选择回填到 v12。在 v12 之前修复 RelationGetBufferForTuple 需要回填一些旧修复程序(特别是 0d1fe9f74),这比修复一个假设性问题所需的代码改动要多。讨论:https://postgr.es/m/2247102.1618008027@sss.pgh.pa.us https://git.postgresql.org/pg/commitdiff/34f581c39e97e2ea237255cf75cccebccc02d477

  • 重新设计 get_cached_rowtype() 的缓存。以前,get_cached_rowtype() 缓存了一个指向 typcache 中引用计数的元组描述符的指针,依赖 ExprContextCallback 机制在销毁使用 tupdesc 的表达式树时释放 tupdesc 的引用计数。这在其设计时工作正常,但引入了块内 COMMIT 会破坏它。引用计数记录在事务生命周期的资源所有者中,但 plpgsql 在 DO 块退出之前不会销毁在 DO 块(在其第一次提交之前)中创建的简单表达式。这会导致 COMMIT 销毁原始资源所有者时出现关于泄漏的 tupdesc 引用计数的警告,然后在销毁表达式时出现关于活动资源所有者不持有匹配引用计数的错误。为了修复,通过缓存相关 typcache 条目的指针来消除对关闭回调的需求。这些条目在后端生命周期内都有效,因此我们不必担心指针过时。(对于注册的 RECORD 类型,我们仍然可以缓存指向 tupdesc 的指针,知道它在后端生命周期内不会改变。)自 commit 4b93f5799 以来,plpgsql 和 expandedrecord.c 中一直在使用此机制,并且似乎工作良好。此更改需要修改相关表达式步骤类型使用的 ExprEvalStep 结构,这对回填来说有点令人担忧。然而,扩展程序似乎没有理由熟悉这些特定子结构的细节。根据 Rohit Bhogate 的报告。回填到 v11,因为块内 COMMIT 成为了可能。讨论:https://postgr.es/m/CAAV6ZkQRCVBh8qAY+SZiHnz+U+FqAGBBDaDTjF2yiKa2nJSLKg@mail.gmail.com https://git.postgresql.org/pg/commitdiff/c2db458c1036efae503ce5e451f8369e64c99541

  • 修复 ALTER ROLE/DATABASE SET 的一些不恰当的禁用用法。大多数检查数据库状态的 GUC 检查钩子都有特殊的检查,可以防止它们因为有状态的问题而抛出硬错误(当 source == PGC_S_TEST 时)。这允许例如“ALTER DATABASE d SET default_text_search_config = foo”在“foo”配置尚未创建时执行。没有它,我们在转储/重新加载或 pg_upgrade 时会遇到问题,因为 pg_dump 对 GUC 值可能的依赖关系一无所知,也无法确保安全的恢复顺序。然而,check_role() 和 check_session_authorization() 没有收到这个信息,并且仍然会抛出硬错误。尚不完全清楚“ALTER ROLE x SET role = y”的用例是什么,但我们已经收到了两次关于此操作破坏升级的独立抱怨,所以显然有人这样做。因此,修复这两个函数,使它们更像其他有类似需求的检查钩子。(但我没有改变它们坚持在事务中运行的要求,因为仍然不清楚从配置文件设置这两个 GUC 是否明智。)还修复了 check_temp_buffers,它有另一种形式的疾病,即在没有 PGC_S_TEST 例外的情况下进行有状态检查。粗略调查其他 GUC 检查钩子未发现更多此类问题。(PGC_POSTMASTER 和 PGC_SIGHUP GUCs 之间存在大量相互依赖关系,这可能不是个好主意,但它们与当前问题无关,因为它们无法通过 ALTER ROLE/DATABASE 设置。)根据 Charlie Hornsby 和 Nathan Bossart 的报告。回填到所有支持的分支。讨论:https://postgr.es/m/HE1P189MB0523B31598B0C772C908088DB7709@HE1P189MB0523.EURP189.PROD.OUTLOOK.COM 讨论:https://postgr.es/m/20160711223641.1426.86096@wrigleys.postgresql.org https://git.postgresql.org/pg/commitdiff/69d5ca484b69771073380e234e5377b6d6a5ebaf

  • 允许在 ON CONFLICT ... WHERE 中使用表限定的变量名。以前这里只能使用未限定的变量名。虽然这不是功能上的缺陷,因为只能引用目标表,但这与部分索引谓词的规则不一致,而该语法据说就是以其为模型。修复方法并不比传递 addToRelNameSpace = true 来 addNSItemToQuery 更难。然而,transformOnConflictArbiter 和 transformOnConflictClause 确实在管理目标表的命名空间项方面有点胡来。它们无权管理,导致命名空间项的重复创建,并且 transformOnConflictClause 甚至没有正确地做到这一点(该代码导致目标表的两个 nsitems,因为它没有清理掉现有的)。因此,让 transformInsertStmt 负责一次性设置这两个子句和 RETURNING 的目标 nsitem。此外,安排在运行 transformOnConflictArbiter 之前,将 ON CONFLICT ... UPDATE 的“excluded”伪关系添加到 rangetable 中。这会在有人在仲裁表达式中写入“excluded.col”时产生一个更有帮助的 HINT。根据 Lukas Eder 的 bug #16958。虽然我同意这是一个 bug,但后果远非严重,因此不回填。讨论:https://postgr.es/m/16958-963f638020de271c@postgresql.org https://git.postgresql.org/pg/commitdiff/6c0373ab77359c94b279c4e67c91aa623841af65

  • 修复了过时的、引用 JoinPathExtraData.extra_lateral_rels 的注释。该字段在 commit edca44b15 中已移除,但似乎 commit 45be99f8c 重新引入了一些提及它的注释。James Coleman 指出,尽管这不完全是他提议的新措辞。也感谢 Justin Pryzby 的软件考古。讨论:https://postgr.es/m/CAAaqYe8fxZjq3na+XkNx4C78gDqykH-7dbnzygm9Qa9nuDTePg@mail.gmail.com https://git.postgresql.org/pg/commitdiff/e1623b7d86812ee6ab98a42f38b43a192c149988

  • 稳定最近添加的 information_schema 测试查询。这些查询可能会显示意外条目,如果核心系统或并发运行的测试脚本创建了任何出现在 information_schema 视图中的函数。将它们限制为仅显示属于此测试的模式的函数,正如更早的附近测试用例那样。通过将一些内置函数转换为 SQL-function-body 样式的实验。 https://git.postgresql.org/pg/commitdiff/3157cbe974846729d49a1ee081944eee1839bdd8

  • 撤销允许 pg_proc.prosrc 为 NULL 的决定。Commit e717a9a18 改变了 prosrc 为 NOT NULL 的长期规则,因为当一个 SQL 语言函数以 SQL 标准风格编写时,我们目前没有有用的东西可以放在那里。这似乎是个糟糕的决定,因为它很容易对外部 PL 产生负面影响(例如,使它们面临以前没有的崩溃)。SQL 函数相关的代码可以轻松地测试“is prosqlbody not null”而不是“is prosrc null”,所以这里也没有真正的收益。因此,恢复 NOT NULL 标记的移除,并调整相关逻辑。目前,我们只是将空字符串放入 SQL 标准函数的 prosrc 中。也许以后我们会有一个更好的主意,尽管像 pg_attrdef.adsrc 这样的东西的历史表明,维护字符串形式的节点树并不容易。这还向 standard_ExecutorStart 添加了一个断言,即 queryDesc->sourceText != NULL。我们已经默默地依赖它一段时间了,所以让它不那么默默。还修复了一些被忽略的文档和测试用例。讨论:https://postgr.es/m/2197698.1617984583@sss.pgh.pa.us https://git.postgresql.org/pg/commitdiff/1111b2668d89bfcb6f502789158b1233ab4217a6

  • 撤销“处理 ExecInitParallelPlan() 中的 NULL 查询字符串”。这撤销了 commit b3ee4c503872f3d0a5d6a7cbde48815f555af15b。在前面的 commit 添加了 upstream 检查,确保 querystring 不为 null 之后,我们不需要它了。讨论:https://postgr.es/m/2197698.1617984583@sss.pgh.pa.us https://git.postgresql.org/pg/commitdiff/83efce7a1ebc5bae79617ddba12a64790141725c

  • 在解析 SQL 标准函数体时提供查询源文本。没有这个,我们会丢失错误光标位置,如修改后的回归测试结果所示。讨论:https://postgr.es/m/2197698.1617984583@sss.pgh.pa.us https://git.postgresql.org/pg/commitdiff/409723365b2708acd3bdf2e830257504bdefac4b

  • 修复两个 ExplainPropertyFloat 调用中的错误单位。这只是一个潜在的错误,因为这些调用只会在非文本输出格式下达到,而目前这些格式都不会打印单位。即便如此,以防万一情况发生变化,我们也应该正确处理。Justin Pryzby 讨论:https://postgr.es/m/20210415163846.GA3315@telsasoft.com https://git.postgresql.org/pg/commitdiff/f90c708a048667befbf6bbe5f48ae9695cb89de4

  • 修复了错误的 collation-version-recording 逻辑。recordMultipleDependencies 的“version”变量范围不正确,允许版本标签从它打算用于排序条目泄漏到后续的非排序条目。这相对难以触发,因为输入通常会按 OID 递减的顺序到达:后续的非排序项倾向于被固定。但使用自定义排序很容易显示出来。另外,不要特殊处理默认排序,而是忽略我们已找到版本的排序的固定性。这避免了创建无用的 pg_depend 条目,并消除了“C、POSIX 和 DEFAULT 是唯一固定的排序”这一不太面向未来的假设。一个小问题是,由于默认排序可能有或可能没有版本,回归测试无法假设是否会为其创建依赖项条目。这似乎还可以,因为现在它与其他排序的处理方式相同,并且我们有版本化和未版本化排序的测试用例。修复了 commit 257836a75 中的疏忽。感谢 Julien Rouhaud 的审查。讨论:https://postgr.es/m/3564817.1618420687@sss.pgh.pa.us https://git.postgresql.org/pg/commitdiff/ef387bed87f2787b1012e68e9a33607a1074c123

  • 将 system_views.sql 中的函数定义拆分到新文件中。创建 system_functions.sql 文件来存放以前在 system_views.sql 中的函数定义。函数定义已经占了该文件四分之一,并且即将更多,因此将其单独存放似乎是合适的。顺便修复了 dfb75e478 中的一个疏忽:它忽略了调用 system_constraints.sql 的 check_input()。讨论:https://postgr.es/m/3956760.1618529139@sss.pgh.pa.us https://git.postgresql.org/pg/commitdiff/e80949372564c126c92aa7d64de483e04c0ef95e

  • 将内置 SQL 语言函数转换为 SQL-standard-body 风格。采用新的预解析表示法来处理所有内置的和 information_schema 的 SQL 语言函数,除了少数目前无法转换的多态参数函数。这消除了这些函数在搜索路径安全方面的残留风险,并可能通过减少解析成本来提供一些小性能提升。提供更多 SQL-standard-body 功能的测试覆盖似乎也很有用。讨论:https://postgr.es/m/3956760.1618529139@sss.pgh.pa.us https://git.postgresql.org/pg/commitdiff/767982e36298be4da44a063e36261e9cfdc0bf49

  • 更新虚拟 prosrc 值。糟糕,我忘了在 767982e36 的这部分 s/system_views.sql/system_functions.sql/g。我认为不需要额外的 catversion 增加,因为这些字符串在 initdb 完成时就已经不存在了。讨论:https://postgr.es/m/3956760.1618529139@sss.pgh.pa.us https://git.postgresql.org/pg/commitdiff/8a2df442b652f83b1c189822737091b90f343965

  • 重新思考提取排序依赖项。目前,find_expr_references_walker() 关注叶节点排序字段,而忽略实际函数和运算符节点的输入排序。这在语义上似乎完全是反的,它会导致报告与表达式行为无关的排序依赖项。因此,重写为检查函数输入排序。这并不完全完美;它未能考虑 record_eq 及其同类项的行为。(之前的代码至少给出了近似值,尽管我认为它很容易被愚弄,从而考虑了不相关的复合类型的列。)我们可能以后会改进这一点,但目前这应该能让那些不喜欢 ef387bed8 的构建农场成员满意。顺便修复了 GetTypeCollations() 中的一些疏忽,并消除了重复的去重。(我担心它仍然可能是 O(N^2) 或更糟,但这使其有所改善。)讨论:https://postgr.es/m/3564817.1618420687@sss.pgh.pa.us https://git.postgresql.org/pg/commitdiff/f24b156997059c257c697b825f022d115825091d

Michaël Paquier 提交

Amit Kapila 提交

Fujii Masao 提交

Peter Eisentraut 提交

Thomas Munro 推送

Noah Misch 推送

Robert Haas 提交

Peter Geoghegan 提交

Tomáš Vondra 提交了

Andrew Dunstan 推送

  • 允许 TestLib::slurp_file 跳过内容,并按需使用。为了避免获取旧的日志文件内容,PostgresNode 中的某些函数执行了以下两种操作之一。在 Windows 上,它会轮换日志文件并重新启动服务器,而在其他地方,它会截断日志文件。这两种操作都是不必要的。我们借鉴了构建农场在这里的做法:在开始之前记录日志文件的大小,然后在获取日志文件时,跳到该位置之前累积内容。在 Windows 上的拼写方式不同,但效果相同。这主要集中在 TestLib 的 slurp_file 函数中,该函数有一个新的可选参数,即在开始读取文件之前跳到的偏移量。客户端中的代码变得更加整洁。回填到所有活动的版本。Michael Paquier,我稍作修改。讨论:https://postgr.es/m/YHajnhcMAI3++pJL@paquier.xyz https://git.postgresql.org/pg/commitdiff/3c5b0685b921533f37622345beb0f8dd49200c01

待处理补丁

Andy Fan 发送了一个补丁,用于记录 RelOptInfo.partexprs 和 nullable_partexprs 的增强功能,并将 gen_prune_steps_from_exprs 分割成更小的块。

Luc Vlaming 发送了另一个补丁修订版,用于添加显式的部分 UNION ALL 路径,并改进并行子查询行计数和成本计算。

Luc Vlaming 发送了另一个补丁修订版,用于通过不发出 LLVMPassManagerBuilderUseInlinerWithThreshold 传递来提高 JIT 性能,并在首次调用时惰性生成 IR 代码。

Amul Sul 发送了另一个补丁修订版,用于实现 ALTER SYSTEM ... READ {ONLY | WRITE}。

James Coleman 发送了一个补丁,为 HashedScalarArrayOp 添加了对 NOT IN 的支持。

Amit Langote 发送了一个补丁,用于修复 PartitionDesc includes_detached 中的一个思绪错误。

Masahiko Sawada 发送了一个补丁,用于修复 REFRESH MATERIALIZED VIEW 的性能退化。

Peter Smith 发送了另一个补丁修订版,为内置逻辑复制添加了对预备事务的支持,并为流式事务添加了 prepare API 支持。

Vigneshwaran C 和交易补丁,用于在 CREATE/ALTER SUBSCRIPTION 中识别发布者丢失的发布。

Vigneshwaran C 发送了一个补丁,用于修复监控统计信息文档的不一致性。

Bruce Momjian 发送了两个补丁修订版,用于修复 pg_stat_activity 中最近添加的查询 ID 的一些命名问题。

Mark Dilger 发送了另外两个补丁修订版,用于向 pg_amcheck 应用程序添加 TOAST 指针损坏检查。

Melanie Plageman 发送了一个补丁,添加了一个系统视图 pg_stat_buffers_written,该视图顾名思义。

Fujii Masao、Kyotaro HORIGUCHI 和 Justin Pryzby 交易补丁,用于修复 TRUNCATE 在外表功能中的一些不当之处。

Justin Pryzby 发送了另外两个补丁修订版,用于完善 14 的文档。

Amit Langote 发送了一个补丁,用于按需初始化 WITH CHECK OPTIONS 和 RETURNING 表达式。

Ekaterina Sokolova 发送了另一个补丁修订版,为 Nested Loop 添加了额外的 Explain 统计信息。

Haiying Tang 发送了另一个补丁修订版,用于支持 psql 中对大写字母输入的查询结果进行选项卡完成。

Dave Page 发送了一个补丁,用于修复 sepgsql 中的一个日志记录问题。

Andrei Zubkov 发送了另一个补丁修订版,用于跟踪 pg_stat_statements 中的语句条目时间戳。

David Christensen 发送了一个补丁,将 pg_size_pretty(numeric) 知道的单位扩展到包括泽字节(yottabytes)。

Bharath Rupireddy 发送了另外两个补丁修订版,以避免在 slot_store_error_callback 和 conversion_error_callback 中访问系统目录。

Masahiko Sawada 和 Peter Geoghegan 交易补丁,以确保 VACUUM 计费的代码注释解释 LP_DEAD 计费。

Ajin Cherian 发送了另外两个补丁修订版,用于跳过逻辑复制中的空事务。

Julien Rouhaud 发送了一个补丁,用于处理与查询 ID 相关的日志记录的一些角落情况。问题在于,一些在语法上有效的查询可能会被记录下来,而忽略了对它们引用的对象在目录中是否存在检查。修复方法是为 log_line_prefix 添加一个 %Q 选项,该选项检查对象是否实际找到。

Zeng Wenjing 和 Shawn Wang 交易补丁,用于实现全局临时表。

Tom Lane 发送了一个补丁,用范围检查替换 pg_depend PIN 条目。

Amul Sul 发送了一个补丁,从 transformCreateStmt 中删除了一个冗余变量。

Pavel Stěhule 发送了两个额外版本的补丁,用于实现模式变量。

Matthias van de Meent 发送了两个补丁修订版,用于记录 ATTACH PARTITION 对默认分区的锁定行为。

Matthias van de Meent 发送了一个补丁,用于实现 _bt_binsrch* 的页级动态前缀截断,然后使用相同的方法实现和使用索引元组属性迭代。

James Coleman、Tomáš Vondra 和 Tom Lane 交易补丁,旨在修复 TPC-DS 查询 94-96 中出现的“无法找到用于排序的 pathkey 项”的 bug。

Masahiro Ikeda 发送了另一个补丁修订版,用于改进 WAL 统计信息报告的性能。

Tomáš Vondra 发送了一个补丁,用于在 generate_orderedappend_path 中生成分数最便宜的路径。

Osumi Takamichi 和 Li Japin 交易补丁,用于修复 TRUNCATE 和同步逻辑复制之间的一个不匹配。

Michaël Paquier 发送了另一个补丁修订版,用于修复逻辑复制工作程序中的 relcache 泄漏。

Mark Dilger 发送了两个补丁修订版,为 pg_amcheck 添加了 --install-missing 选项。

Sven Klemm 发送了一个补丁,用于修复 pg_event_trigger_ddl_commands,在同一事务中删除对象的情况下,它可能会查看无效的缓存。

Andy Fan 发送了一个补丁,用于确保 set_append_rel_size 考虑初始分区裁剪。

Tom Lane 发送了一个补丁,用于在重复子查询提取中节省一些周期。