发布说明

PostgreSQL 17.8

E.2. 发布版本 17.8 #

发布日期:. 2026-02-12

本次发布包含来自 17.7 的多项修复。 有关 17 主版本新特性的说明,请参见 Section E.10

E.2.1. 迁移到版本 17.8 #

对于运行 17.X 的用户,不需要执行导出/恢复。

但是,如果你从早于 17.6 的版本升级,请参见 Section E.4

E.2.2. 变更 #

  • 防范 oidvector/int2vector 出现意外维度的情况(Tom Lane) §

    这些数据类型本应是不包含空值的一维数组,但某些类型转换路径允许违反这些预期。为一些原本依赖这些前提却未加验证的函数增加检查,以避免因此出现异常行为。

    PostgreSQL 项目感谢 Altan Birler 报告此问题。 (CVE-2026-2003)

  • 加固选择率估算器,防止其被附加到接受意外数据类型的操作符上(Tom Lane) § § §

    contrib/intarray 中包含一个选择率估算函数,由于没有检查输入是否为预期的数据类型,可能被滥用于执行任意代码。第三方扩展也应检查类似风险,并采用 intarray 现在使用的技术加以防护。鉴于这类扩展修复需要时间,我们现在要求只有超级用户才能将非内置的选择率估算器附加到操作符上。

    PostgreSQL 项目感谢 Daniel Firer(zeroday.cloud)报告此问题。 (CVE-2026-2004)

  • 修复 contrib/pgcrypto 的 PGP 解密函数中的缓冲区越界问题(Michael Paquier) §

    使用超长会话密钥解密特制消息会导致缓冲区越界,其后果可能严重到与任意代码执行相当。

    PostgreSQL 项目感谢 Team Xint Code(zeroday.cloud)报告此问题。 (CVE-2026-2005)

  • 修复对多字节字符长度验证不足的问题(Thomas Munro、Noah Misch) § § § § § §

    多个缺陷使得能够发出特制 SQL 的攻击者有机会突破字符串缓冲区,其后果可能严重到与任意代码执行相当。修复之后,当字符串函数处理已经存储在数据库中的无效文本时,应用程序可能会观察到 编码的字节序列无效 错误。

    PostgreSQL 项目感谢 Paul Gerste 和 Moritz Sanft(zeroday.cloud)报告此问题。 (CVE-2026-2006)

  • 不允许子选择中的 CTE 引用决定聚合函数的语义级别(Tom Lane) §

    这一修改撤销了两次小版本之前所做的一项更改。现在,如果子选择引用了一个 CTE,而该 CTE 所处的语义级别低于标准 SQL 规则根据其中包含的列引用和聚合所应赋予该聚合函数的语义级别,就会报错。先前尝试的修复本身又带来了问题,而替代方案目前并不明确。由于 SQL 标准本就完全不允许在聚合内部出现子选择,因此将这类情况视为错误似乎已经足够。

  • 修复 CTE 查询中 MERGE 的触发器转移表捕获问题(Dean Rasheed) §

    在执行会修改数据的 CTE 查询时,如果其中既包含 MERGE,又对具有语句级 AFTER 触发器的表执行其他 DML 操作,则传递给触发器的转移表将不包含受 MERGE 影响的行,只包含受其他操作影响的行。

  • 修复在更新或删除的分区目标表的所有子表都被剪枝时的失败问题(Amit Langote) §

    在这种情况下,即使实际上无需执行任何操作,执行器也可能报告 could not find junk ctid column 错误。

  • 避免在查询包含重复窗口函数调用时可能出现的规划器失败(Meng Zhang、David Rowley) §

    对这类调用去重时的混乱可能导致诸如 WindowFunc with winref 2 assigned to WindowAgg with winref 1 之类的错误。

  • 即使索引谓词已蕴含 WHERE 子句的真实性,也允许在部分哈希索引上执行索引扫描(Tom Lane) §

    通常我们会移除由谓词蕴含的 WHERE 子句,因为再测试它毫无意义;它对每个索引条目都必然成立。但如果索引像哈希索引那样要求前导索引键上必须有 WHERE 子句,这就可能阻止生成索引扫描计划。因此,在考虑此类索引时,不要移除被蕴含的子句。

  • 不要为不记录日志的 BRIN 索引生成 WAL(Kirill Reshke) §

    某条很少走到的代码路径即使在索引被标记为不记录日志时,也会错误地生成与 BRIN 索引相关的 WAL 记录。这样一来,崩溃恢复在重放该记录时会失败,并报称该文件已存在。

  • 防止截断未读 NOTIFY 消息仍然需要的 CLOG(Joel Jacobson、Heikki Linnakangas) § § §

    此修复可防止在后端缓慢接收 NOTIFY 消息时出现 could not access status of transaction 错误。

  • NOTIFY 消息处理过程中发生的错误升级为 FATAL,也就是关闭连接(Heikki Linnakangas) §

    以前,如果后端在接收 NOTIFY 消息时出错,它会跳过该消息、向客户端报告错误,然后继续处理后续消息。但这种行为问题很多。一个重大问题是,客户端没有可靠办法知道某条通知已经丢失,更不可能知道丢失通知的内容。根据应用逻辑不同,漏掉一条通知可能会让应用卡在那里一直等待。并且,任何剩余消息都要等到有人再次发送新的 NOTIFY 才会继续处理。

    此外,如果连接在收到 NOTIFY 信号时正处于空闲状态,出于其他方面的考虑,任何 ERROR 本来也都会被升级为 FATAL。因此,我们决定在所有情况下都这样处理,以保持一致性,并向应用程序发出清晰信号,表明它可能错过了一些通知。

  • 修复在发生并发更新时 EXPLAIN ANALYZE MERGE 对更新计数错误的问题(Dean Rasheed) §

    这种情况会导致 EXPLAIN 输出中的 skipped 元组计数错误,或者在启用断言的构建中引发断言失败。

  • 修复锁定元组时沿更新链跟进的错误(Jasper Smit) §

    这段代码路径忽略了检查更新链中第一个新元组的 xmin,因此如果原始更新者中止,而空间又立即被 VACUUM 回收并重新使用,就有可能锁定到一个无关的元组。这可能导致意料之外的事务延迟或死锁。也已经观察到由于识别错元组而引发的错误。

  • 修复原地更新系统目录时的问题(Noah Misch) § § §

    对于原地更新,发送非事务性的失效消息,因为此类更新在事务回滚后仍会保留。同时,确保该更新在其他会话可见之前已经写入 WAL。这些修复主要防止关系的 frozen-XID 属性出现不一致,从而避免 CLOG 被过早截断并随后出现 could not access status of transaction 错误。

  • 修复对大表增量备份处理不正确的问题(Robert Haas、Oleg Tkachenko) §

    如果一个超过 1GB 的表(更一般地说,超过安装的段大小的表)在基础备份和增量备份之间被 VACUUM 截断,pg_combinebackup 可能会因 truncation block length in excess of segment size 错误而失败,从而无法恢复该增量备份。

  • 修复进程退出时可能发生的后端进程崩溃问题,其原因是试图在已取消映射的共享内存段中释放锁(Rahila Syed) §

  • 防止崩溃后多事务日志被错误截断(Heikki Linnakangas) §

  • 修复 pg_stat_get_backend_activity() 结果可能被错误编码的问题(Chao Li) §

    保存会话活动字符串的共享内存缓冲区可能会以不完整的多字节字符结尾。读取方本应截掉这种不完整字符,但这个函数没有这样做。

  • 防止内存上下文日志记录发生递归(Fujii Masao) §

    如果请求记录内存上下文的信号持续不断,可能导致日志代码递归执行,理论上会造成栈溢出。

  • 修复重新初始化并行执行上下文时的内存上下文使用问题(Jakub Wartak、Jeevan Chalke) §

    由于某个附属数据结构的生命周期比并行上下文更短,这一错误可能导致崩溃。目前尚不清楚仅使用核心 PostgreSQL 是否能触发该问题,但我们已经收到扩展中出现问题的报告。

  • 在创建新的 multixid 时设置下一个 multixid 的偏移量,以移除只在边角场景才需要的等待循环(Andrey Borodin) § §

    先前的逻辑可能会卡住,等待一个永远不会发生的更新。

  • 避免对会修改数据的 CTE 重写多次(Bernice Southey、Dean Rasheed) §

    以前,在更新自动可更新视图或带有规则的关系时,如果原始查询中包含任何会修改数据的 CTE,重写器就会因为递归而多次重写这些 CTE。这不仅效率低,还可能在 CTE 包含对始终生成列的更新时产生错误。

  • 允许重试 DSM 注册表条目的初始化(Nathan Bossart) §

    如果动态共享内存条目的初始化进行到一半失败,允许下一次尝试使用该条目时重新初始化。此前,该条目会永久处于失败状态。

  • 如果检查点记录指示的重做点之前的 WAL 不存在,则让恢复失败(Nitin Jadhav) §

    在开始恢复前增加显式检查,以确保不会造成损害并能提供有用的错误消息。此前,恢复在这种情况下可能崩溃或损坏数据库。

  • 避免在 ALTER PUBLICATION 期间改写源查询树(Sunil S) §

    这一错误在可见层面的表现是:为该查询触发的事件触发器即使指定了多个 publish 选项,也只能看到第一个。如果把这样的查询设置为预备语句,后续重新执行也会行为异常。

  • CREATE SUBSCRIPTION ... CONNECTION 中指定的连接选项传递给发布端的 walsender(Fujii Masao) §

    在此修复之前,options 连接选项(如果有)会被忽略,因此例如无法在 walsender 会话中设置自定义服务器参数值。这个功能原本就应该可用,而且在 PostgreSQL 15 的重构破坏它之前也确实可用,因此这里恢复了此前的行为。

  • 防止新创建或新同步的复制槽被标记为无效(Zhijie Hou) § § §

    与并发检查点之间的竞争条件可能会让复制槽所需的 WAL 被移除,从而导致该槽立即被标记为无效。

  • 修复计算复制槽所需 xmin 时的竞争条件(Zhijie Hou) §

    这可能导致报错 cannot build an initial slot snapshot as oldest safe xid follows snapshot's xmin

  • 在逻辑复制订阅的初始同步期间,在开始复制数据之前先提交新增的 pg_replication_origin 条目(Zhijie Hou) §

    以前,如果复制步骤失败,新的 pg_replication_origin 条目会因事务回滚而丢失。这会导致共享内存中的状态不一致。

  • 在并行工作进程 apply 失败后,不要推进逻辑复制进度(Zhijie Hou) §

    先前的行为可能导致订阅端丢失事务。

  • 修复逻辑复制 slotsync 工作进程对 LOCK_TIMEOUT 信号的处理(Zhijie Hou) §

    以前,这类超时信号实际上会被忽略。

  • 修复流复制备库服务器重启时可能出现 unexpected data beyond EOF 失败的问题(Anthonin Bonnefoy) §

  • 修复 SQL/JSON 路径类型不匹配时的错误报告(Jian He) §

    该代码原本应报告路径表达式类型不正确,却可能产生 cache lookup failed for type 0 错误。

  • 修复解析分区范围边界时对列位置跟踪错误的问题(myzhen) §

    例如,这可能导致在把分区边界值转换为列的数据类型时,错误消息引用了错误的列名。

  • 修复错误消息中的若干细小错误(Man Zeng、Tianchen Zhang) § § § § §

    例如,关于备份清单中时间线编号不匹配的错误报告,本来应该显示结束时间线编号,却显示成了起始时间线编号。

  • 修复在使用 LLVM 17 及更高版本进行 JIT 编译时无法执行函数内联的问题(Anthonin Bonnefoy) §

  • 调整我们的 JIT 代码以兼容 LLVM 21(Holger Hoffstätte) §

    先前的代码在 aarch64 机器上无法编译。

  • 新增服务器参数 file_extend_method,用于控制是否使用 posix_fallocate()(Thomas Munro) §

    PostgreSQL 16 及以上版本如果平台提供 posix_fallocate(),就会使用它来扩展关系文件。然而,据报告它与某些文件系统配合得并不好:使用 posix_fallocate() 会禁用 BTRFS 压缩,而在较旧版本的 Linux 内核上,XFS 可能会产生伪造的 ENOSPC 错误。为提供一种变通办法,引入了这个新的服务器参数。将 file_extend_method 设为 write_zeros 会让服务器恢复到通过写入零块来扩展文件的旧方法。

  • 在 Windows 上遵从 open()O_CLOEXEC 标志(Bryan Green、Thomas Munro) § § §

    让该标志像在 POSIX 平台上一样工作,以免文件句柄泄漏到诸如 COPY TO/FROM PROGRAM 之类的子进程中。虽然这种泄漏尚未造成很多问题,但显然不理想。

  • 修复使用 meson 构建的 Solaris 可执行文件无法在服务器命令行上解析长选项的问题(Tom Lane) §

  • 支持在 GNU/Hurd 上更改进程标题(Michael Banck) §

  • 避免 pg_dump 在 binary-upgrade 模式下触发断言失败(Vignesh C) §

    对象排序代码未能处理订阅关系对象,从而触发断言,不过在生产构建中并未发现严重的实际影响。

  • 修复 pipeline 模式下 pgbench 在有多个 \syncpipeline 命令时的错误处理问题(Yugo Nagata) §

    如果在查询错误之后又遇到多个 \syncpipeline 命令,pgbench 会报告 failed to exit pipeline mode,或者在启用断言的构建中触发断言失败。

  • pg_resetwal 在更改 OldestXID 时打印更新后的值(Heikki Linnakangas) §

    对它可以更改的其他每个变量都已经这样做了。

  • pg_resetwal 允许把下一个 multixact xid 设为 0,或把下一个 multixact offset 设为 UINT32_MAX(Maxim Orlov) §

    这些都是有效值,因此拒绝它们是不正确的。最坏情况下,如果恰好在 multixact 回卷点上尝试 pg_upgrade,升级将失败。

  • contrib/amcheck 中,对 btree 索引父页检查使用正确的快照(Mihail Nikalayeu) § §

    先前的代码在检查通过 CREATE INDEX CONCURRENTLY 创建的索引时会产生伪错误。

  • 修复 contrib/amcheckhalf-dead btree 索引页的处理(Heikki Linnakangas) §

    amcheck 认为这类页面应当有一个父 downlink,但实际上并没有,因此会错误报告 mismatch between parent key and child high key

  • 修复 contrib/amcheck 对不完整的 btree 根页分裂的处理(Heikki Linnakangas) §

    amcheck 可能会错误报告 block is not true root

  • 修复 contrib/intarray@@ 选择率估算器的边界情形整数溢出问题(Chao Li) §

    这可能导致在涉及最大整数值的情况下生成很差的选择率估算。

  • 修复 contrib/ltree 中的多字节编码问题(Jeff Davis) §

    先前的代码可能会把不完整的多字节字符传给 lower(),很可能导致错误行为。

  • 将时区数据文件更新为 tzdata 2025c 版(Tom Lane) §

    唯一的变更是 Baja California 1976 年之前时间戳的历史数据。