发布说明

PostgreSQL 18.2

E.2. 发布版本 18.2 #

发布日期:. 2026-02-12

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

E.2.1. 迁移到版本 18.2 #

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

但是,如果你在 ltree 列上建有索引,则更新后可能需要对其重新索引。请参见下方第六条变更记录。

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)

  • 加固 contrib/pg_trgm,以应对字符串转小写行为的变化(Heikki Linnakangas) § §

    修复潜在的缓冲区越界问题,因为在某些区域设置中,将字符串转换为小写后产生的字符数可能多于原始字符串中的字符数(而非字节数)。这种行为是版本 18 中新增的,因此该缺陷也是新引入的。

    PostgreSQL 项目感谢 Heikki Linnakangas 报告此问题。 (CVE-2026-2007)

  • 修复 contrib/ltree 中不一致的大小写不敏感匹配问题(Jeff Davis) § §

    ltree 中与索引相关的例程所使用的大小写折叠实现与主操作符不同。只有在默认排序规则提供者为 libc 且编码为单字节时,两者行为才一致。

    为修复该问题,代码已改为使用数据库默认排序规则的大小写折叠行为。除非数据库使用 libc 作为排序规则提供者且其编码为单字节,否则此更改要求对 ltree 列上的索引重新建立索引(无论索引访问方法为何)。否则,使用这些索引的搜索将无法找到相关条目。

  • 使用 ALTER TABLE ... ADD CONSTRAINT 为列添加显式命名的非空约束时,如果该列已经标记为 NOT NULL,则要求所提供的名称与现有约束名称一致(Álvaro Herrera、Srinath Reddy Sadipiralla)。 §

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

    这一修改取消了先前两次小版本的修改,相反,如果一个子选择引用一个低于标准 SQL 规则根据包含的列引用和集合分配的语义级的CTE,则会出现错误。 尝试的修补结果造成了自己的问题,现在还不清楚该怎么办。 由于SQL标准完全不允许在总量内进行子选择,将此类情况作为错误处理似乎就足够了。

  • 固定触发过渡表格抓取 MERGE 在CTE查询(Dean Rasheed)中 §

    当执行一个数据修改的 CTE 查询时,该查询包含一个 MERGE 和表格上具有语句级别的另一个 DML 操作 AFTER 中,转录到触发器的过渡表不包括受触发器影响的行。 MERGE,仅指受其他行动影响的人。

  • 修正属于非关系范围条目的行标记的不正确浏览, 如子序列( Dean Rasheed) §

    如果需要通过EvalPlanQual的重新检查来修改拟议的行更新,结果就会不正确,如果该行同时更新,情况也可能如此。

  • 当更新或删除的分区目标表格的所有儿童都已被刷新(Amit Langote)时修复失败 §

    在这种情况下,执行人可以报告 找不到垃圾 ctid 栏 错误,尽管不需要做什么。

  • 修正数组下标中子选择的表达式评价错误( Andres Freund) §

  • 修正文本子字符串搜索, 用于非决定性的整理( Laurenz Albe) §

    在使用非决定性的整理时,我们未能发现在搜索字符串的末尾发生的匹配.

  • 当查询包含重复的窗口功能调用时,避免可能的计划失败(Meng Zhang, David Rowley) §

    由于这种电话的复发而产生困惑,可能造成错误,如: 使用 winref 2 的 WindowFunc 分配给使用 winref 1 的 WindowAgg.

  • 用设置返回函数和组合集修复规划器错误(Richard Guo) §

    在构建ProjectSet计划节点时,计划员未能发现涉及分组表达式的子表达式已经由输入计划计算出来. 这导致了计划效率低下或错误,例如: 子计划目标列表中找不到的变量.

  • 避免在子query的分组条款包含挥发或设置返回功能时不正确的优化(Richard Guo) §

    规划器会尝试下推引用此类分组列的外层查询限制,这会因为对易变函数进行多次求值而导致错误行为,或者因将返回集合的函数引入子查询的 WHERE/HAVING 子句而报错。

  • 在搜索表达式的统计信息时穿透 PlaceHolderVar 节点(Richard Guo) §

    此更改允许规划器找到从子查询上拉出来的表达式,或用于 GROUP BY 的表达式的相关统计信息,从而避免退回到默认估算值。(严格来说,我们也许应该调整找到的统计信息,以反映该值为 NULL 的概率增加,但对于普通 Var 我们也从未做过同等处理。)这一限制虽由来已久,但 PostgreSQL 18 让 PlaceHolderVar 的出现比以前更常见,因此做出此修改以避免受影响场景中的计划回退。

  • 在将表达式匹配到索引时穿透无操作的 PlaceHolderVar 节点(Richard Guo) §

    由于 PostgreSQL 18 在更多场景下使用 PlaceHolderVar,一些原本可以使用索引的查询反而不能使用索引了。新增相应逻辑以防止这种回退。

  • 修复规划器将 OR 子句转换为 ScalarArrayOp 索引条件时的问题(Tender Wang、Tom Lane) §

    该代码未能正确处理 RelabelType 节点,可能生成无效表达式,或者无法完成本应有效的转换。

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

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

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

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

  • 在并行 GIN 索引构建中使用正确的排序函数(Tomas Vondra) §

    并行代码使用了默认排序操作符(由列数据类型的 btree 操作符类决定),而它本应在存在时使用 GIN 操作符类指定的排序函数。如果该数据类型没有 btree 操作符类,就会失败;如果操作符类指定的排序函数与 btree 操作符类不一致,则会生成无效索引。

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

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

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

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

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

  • 在计算查询 ID 哈希时纳入分组表达式(Jian He) §

    以前,两个除了 GROUP BY 表达式不同之外其余都相同的查询,会被 contrib/pg_stat_statements 以及其他使用查询 ID 的模块合并在一起。

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

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

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

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

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

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

  • 在进程退出时修复可能的后端进程崩溃, 原因是试图释放一个锁定, 位于一个已无法配置的共享内存部分( Rahila Syed) §

  • 修复异步 I/O 代码中的竞争条件(Andres Freund) §

    异步 I/O 操作的结果码有可能在被读取之前就被覆盖。

  • 防止崩溃后多事务日志被错误截断(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) §

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

  • 避免在页面被换出时 NUMA 状态视图失败(Tomas Vondra) §

  • 避免在使用较旧 libnuma 版本查询 NUMA 页面状态时出现 operation not permitted 错误(Tomas Vondra) §

  • 如果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 机器上无法通过编译。

  • 修复 aarch64 专用代码,使其可与旧版(RHEL7 时代)的系统头文件一起构建(Tom Lane) § §

  • 修复对 io_uring_queue_init_mem() 的错误 configure 检测(Masahiko Sawada) §

    该错误导致在基于 autotools 的构建中无法优化异步 I/O 缓冲区分配,尽管使用 meson 构建时这段代码是可用的。这个遗漏的主要影响是后端进程退出速度比应有的更慢。

  • 添加新服务器参数 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) §

  • 修复 psqlVACUUM 选项值的 Tab 补全(Yugo Nagata) §

  • psql 命令提示符中,如果没有服务器连接,则不要显示 %P(管道状态)的值(Chao Li) §

    这使 %P 的行为与其他依赖当前活动连接的提示符转义序列保持一致。

  • 修复 pg_dump 收集序列值的逻辑(Nathan Bossart) § §

    如果某个序列在转储过程中被并发删除,pg_dump 会失败,即使该序列并不在待转储的数据库对象中。另外,如果调用用户没有权限读取序列值,pg_dump 先前会输出错误的值,而不是像预期那样失败。

  • 修复 pg_dumpoauth_validator_libraries 取值的引号处理可能不正确的问题(ChangAo Chen) §

    如果 pg_dump 需要转储该设置的值,它此前会应用错误的引用规则。

  • 避免 pg_dump 在二进制升级模式下触发断言失败(Vignesh C) §

    对象排序代码未能处理 subscription-relation 对象,从而触发断言;不过在生产构建中并未造成严重后果。

  • 修复 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/amcheck,使其能够正确处理 half-dead 的 btree 索引页(Heikki Linnakangas) §

    amcheck 先前以为这类页面会有父向下链接,但实际上并没有,因此会错误报告 mismatch between parent key and child high key

  • 修复 contrib/amcheck,使其能够正确处理不完整的 btree 根页分裂(Heikki Linnakangas) §

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

  • 修复 contrib/pg_buffercache 中过度分配内存的问题(David Geier) §

    代码分配的内存是NUMA页面状态需要的两倍.

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

    这可能导致在涉及最大整数值的场景中产生糟糕的选择率估算。

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

    先前的代码可能把一个不完整的多字节字符传给 lower(),从而导致不正确的行为。

  • 避免当 contrib/pg_stat_statements 处理包含常量和非常量表达式的 IN 列表时发生崩溃(Sami Imseih) §

  • 更新时区数据文件至 tzdata 2025c(汤姆巷) §

    唯一的变化是下加利福尼亚州1976年以前的时间戳的历史数据.