发布说明

PostgreSQL 16.10

E.4. 发布版本 16.10 #

发布日期:. 2025-08-14

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

E.4.1. 迁移到版本 16.10 #

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

但是,如果你有任何 BRIN numeric_minmax_multi_ops 索引,建议在更新后对其进行重建索引。 请参见下面的第四条变更日志条目。

此外,如果你从早于 16.9 的版本升级,请参见 Section E.5

E.4.2. 变更 #

  • 加强规划器估算函数中的安全检查 (Dean Rasheed) §

    针对 CVE-2017-7484 的修复以及后续修复,旨在防止泄漏函数被应用于调用用户无权读取的列的统计数据。 已发现该保护中存在两个漏洞。一个漏洞适用于分区和继承层次结构,其中表上的 RLS 策略应限制对统计数据的访问,但实际上并未限制。

    另一个漏洞适用于查询通过视图访问表的情况,其中视图所有者有权读取底层表,但调用用户对该视图没有权限。 视图所有者的权限满足了安全检查,而泄漏函数会在我们检查调用用户对视图的权限之前就被应用于底层表的统计数据。 此问题已通过在规划开始时执行视图安全检查来修复。这可能会导致权限失败比以前更早发生。

    PostgreSQL 项目感谢 Dean Rasheed 报告此问题。 (CVE-2025-8713)

  • 防止 pg_dump 脚本被用来攻击执行恢复的用户 (Nathan Bossart) §

    由于导出/恢复操作通常涉及以超级用户身份运行 SQL 命令,目标数据库安装必须信任源服务器。 然而,这并不意味着执行 psql 进行恢复的操作系统用户也应该信任源服务器。 此处的风险在于,获得源服务器超级用户级别控制权的攻击者可能会使其发出被解释为 psql 元命令的文本。 这将提供对恢复用户自身账户的 shell 级别访问,独立于对目标数据库的访问。

    为了提供对此类攻击的正面保证,扩展 psql 增加了 \restrict 命令以阻止执行进一步的元命令,并让 pg_dump 在来自源服务器的任何数据之前发出该命令。

    PostgreSQL 项目感谢 Martin Rakhmanov、Matthieu Denais 和 RyotaK 报告此问题。 (CVE-2025-8714)

  • pg_dump 输出中注释内包含的名称中的换行符转换为空格 (Noah Misch) §

    包含换行符的对象名称提供了向输出脚本注入任意 SQL 命令的能力。 (如果没有前面的修复,通过这种方式注入 psql 元命令也是可能的。) CVE-2012-0868 在当时修复了这类问题,但后来的工作重新引入了多个此类情况。

    PostgreSQL 项目感谢 Noah Misch 报告此问题。 (CVE-2025-8715)

  • 修复 BRIN numeric_minmax_multi_ops 支持函数中不正确的距离计算 (Peter Eisentraut、Tom Lane) §

    在 64 位平台上结果有时是错误的,在 32 位平台上则严重错误。 这不会产生明显的故障,因为该逻辑仅用于选择如何将值合并到范围中;最坏情况下索引会变得低效和膨胀。 尽管如此,建议重建任何使用 numeric_minmax_multi_ops 操作符类的 BRIN 索引。

  • 避免我们可接受的 XML 输入大小出现退化 (Michael Paquier、Erik Wienhold) § §

    我们针对 libxml2 早期 2.13.x 版本中一个错误的解决方法使用了一个拒绝超过 10MB 文本块的代码路径, 而之前的代码并没有这一限制。那些早期版本在实际中大概已经不存在了,因此恢复到之前的代码。

  • 修复对普通继承父表执行 MERGE 的问题 (Dean Rasheed) §

    对此类目标表的插入操作可能崩溃或产生不正确的查询结果,原因是未能处理 WITH CHECK OPTIONRETURNING 操作。

  • 允许具有语句级触发器的表成为分区或继承子表 (Etsuro Fujita) §

    我们不允许分区或继承子表具有带有转换表的行级触发器,因为对整个继承树的操作需要为每个此类子表维护单独的转换表。 但这个问题不适用于语句级触发器,因为只有父表的语句级触发器会被触发。 检查现有表是否可以成为分区或继承子表的代码却拒绝了两种类型的触发器。

  • 禁止从子外部表收集转换元组 (Etsuro Fujita) §

    我们不支持在外部表上使用带有转换表的触发器。 然而,分区或继承子表是外部表的情况被忽略了。 如果父表有这样的触发器,则从外部子表收集了不正确的转换元组。 现在改为抛出错误,报告该情况不受支持。

  • 允许重置具有保留前缀的未知自定义参数 (Nathan Bossart) §

    之前,如果一个参数设置是通过 ALTER DATABASE/ROLE/SYSTEM 存储的, 在该参数未知但具有保留前缀的情况下,已存储的设置无法被移除。 这种情况可能在扩展曾经有一个参数,但该参数在升级中已被移除时出现。

  • 修复在 ALTER SUBSCRIPTION ... DROP PUBLICATION 期间可能发生的死锁 (Ajin Cherian) §

    确保服务器进程在删除复制来源时以一致的顺序获取目录锁。

  • 缩短创建具有冲突名称的索引时的竞态条件窗口 (Tom Lane) §

    在为索引选择自动生成的名称时,除了完全有效的行之外,还要避免与尚未提交的 pg_class 行冲突。 这避免了可能选择与某个并发 CREATE INDEX 相同名称的情况, 当该命令仍在填充其索引,或已完成但属于尚未提交的事务的一部分时。 仍然存在出问题的窗口,但仅限于验证新索引参数并插入其 pg_class 行所需的时间。

  • 防止在单个命令中对多个表执行清理时使用不正确的 VACUUM 选项 (Nathan Bossart、Michael Paquier) §

    一个表的 TRUNCATEINDEX_CLEANUP 选项可能被应用到其他表上。

  • 修复 SIMILAR TO 正则表达式中字符类的处理 (Laurenz Albe) § §

    SIMILAR TO 模式匹配表达式转换为 POSIX 风格正则表达式的代码没有考虑到方括号可以嵌套。 例如,在 [[:alpha:]%_] 这样的模式中,代码将 %_ 字符视为元字符,而它们应该是字面量。

  • 在反解析查询时,始终为 FETCH FIRST expression ROWS WITH TIES 子句中的表达式添加括号 (Heikki Linnakangas) § §

    这避免了一些反解析结果在语法上无效的情况。

  • 限制检查点进程的 fsync 请求队列大小 (Alexander Korotkov、Xuneng Zhou) § §

    shared_buffers 设置非常大时,检查点进程可能尝试为 fsync 请求分配超过 1GB 的内存, 导致失败并进入无限循环。限制队列大小以防止这种情况。

  • 避免在逻辑解码读取部分写入的 WAL 记录时发生无限等待 (Vignesh C) §

    如果服务器在写入一条跨越多个页面的 WAL 记录的第一部分后崩溃,后续对 WAL 流的逻辑解码将等待下一个 WAL 页面上的数据到来。 如果服务器现在处于空闲状态,这可能永远不会发生。

  • 修复 ACL 字符串中角色名称引用不一致的问题 (Tom Lane) §

    之前的引用规则依赖于区域设置,这在跨安装传输 aclitem 值时可能导致可移植性问题。 (pg_dump 不会这样做,但其他工具可能会。) 为确保一致性,在 aclitem 输出中始终对非 ASCII 字符进行引用; 但为了保持向后兼容性,在 aclitem 输入期间绝不要求它们被引用。

  • 拒绝关系选项和外部数据选项名称中的等号(=) (Tom Lane) §

    没有明显的用途需要此类选项名称,允许它们会在存储表示中造成歧义。

  • 修复 LZ4 压缩归档数据可能不正确的解压缩问题 (Mikhail Gribkov) §

    此错误似乎只在压缩率不高的输入数据上才会出现,这可能解释了为何它一直未被发现。

  • 避免一种罕见情况,即 B-树索引扫描可能将错误的索引条目标记为已删除 (Peter Geoghegan) §

  • 避免在逻辑复制期间重新分发来自其他事务的缓存失效消息 (vignesh C) §

    我们上一轮小版本发布包含了一个错误修复,以确保复制接收进程能够响应跨进程缓存失效消息, 防止它们在执行复制更新时使用过期的目录数据。然而,该修复无意中使它们也重新分发了这些消息, 导致失效消息数量呈指数级增长,通常最终以内存分配失败告终。 通过不重新分发接收到的消息来修复此问题。

  • 避免在检查点期间过早移除旧的 WAL (Vitaly Davydov) §

    如果在检查点进行期间复制槽的重启点被推进,不再需要的 WAL 段可能被过早移除, 导致在数据库紧接着崩溃时恢复失败。通过多保留一个检查点周期来修复此问题。

  • 绝不将复制槽的已确认刷新位置向后移动 (Shveta Malik) §

    在某些情况下,复制客户端可能确认了一个超过其持久化存储的 LSN,然后在重启后可能发送一个较旧的 LSN。 只要客户端对两个点之间的 WAL 不需要做任何事情,我们就认为这不是错误。 然而,我们不应该重新发送那些 WAL 以避免数据重复,因此确保我们始终信任给定槽的最新确认 LSN。

  • 防止启动新的逻辑复制工作进程之前出现过长延迟 (Tom Lane) §

    在某些情况下,逻辑复制启动器在启动新工作进程之前的休眠时间可能远超配置的 wal_retrieve_retry_interval

  • 修复在逻辑复制 INSERT ... ON CONFLICT 时的释放后使用问题 (Ethan Mertz、Michael Paquier) §

    这可能导致不正确的进度报告,如果运气非常不好还可能导致 WAL 发送进程崩溃。

  • 允许在备库上等待事务完成时被中断 (Kevin K Biju) §

    在备库上创建复制槽可能需要等待主库上的某些活动事务完成,然后在备库上重放。 由于这可能是一个无限期的等待,因此允许操作被取消是可取的,但循环中没有检查查询取消。

  • 不允许级联逻辑 WAL 发送者尝试发送超出其备库上已重放内容的数据 (Alexey Makhmutov) §

    这避免了此类 WAL 发送者在备库关闭时卡住的情况, 因为它们在等待不会发生的重放工作,而服务器的启动进程已经关闭。

  • 修复自动清理中的每关系内存泄漏 (Tom Lane) §

  • 修复 XMLSERIALIZE(... INDENT) 中的会话生命期内存泄漏 (Dmitry Kovalenko、Tom Lane) § §

  • 修复某些地方可能在没有任何快照的情况下尝试获取系统目录的 toasted 字段的问题 (Nathan Bossart) §

    这可能导致断言失败或 cannot fetch toast data without an active snapshot 错误。

  • 避免在跨表约束更新期间的断言失败 (Tom Lane、Jian He) § §

  • 移除在 PortalRunMulti() 结束时必须确定命令标签的错误断言 (Álvaro Herrera) §

    这在边界情况下会失败,例如空的预备语句。

  • 修复 XMLTABLE 解析中的断言失败 (Richard Guo) §

  • 恢复在并行模式下运行 PL/pgSQL 表达式的能力 (Dipesh Dhameliya) §

    PL/pgSQL 对表达式的概念非常宽泛, 涵盖任何返回单列且不超过一行的 SQL SELECT 查询。 因此存在一些情况,例如对聚合函数的求值,其中查询涉及大量工作, 使用并行工作进程来运行它是有用的。这以前是可能的,但之前的一个错误修复无意中禁用了它。

  • 修复 PL/Python 错误报告中的边界情况资源泄漏 (Tom Lane) § §

    在报告来自 Python 的错误时发生的内存不足故障可能导致未能释放 Python 对象的引用计数, 从而导致会话生命期的内存泄漏。

  • 修复 libpqPQport() 函数,使其除非传入的连接为 NULL,否则永远不返回 NULL (Daniele Varrazzo) §

    这是文档中记录的行为,但最近的 libpq 版本在用户未提供端口规范的某些情况下会返回 NULL。 恢复到我们历史上在此类情况下返回空字符串的行为。 (v18 及更高版本将改为返回编译时的默认端口号,通常为 "5432"。)

  • 避免在 GSSAPI 认证需要大于 16kB 的数据包时出现故障 (Jacob Champion、Tom Lane) §

    属于多个 AD 组的 Active Directory 用户需要较大的认证数据包。 此限制表现为连接失败并出现难以理解的错误消息, 通常为 GSSAPI context establishment error: The routine must be called again to complete its function: Unknown error

  • 修复 SSL 和 GSSAPI 数据传输中的时序相关故障 (Tom Lane) §

    在非阻塞模式下使用 SSL 或 GSSAPI 加密时,libpq 有时会失败, 并报告 SSL error: bad lengthGSSAPI caller failed to retransmit all data needing to be retried

  • 避免在 ecpg 应用程序中连接查找时的空指针解引用 (Aleksander Alekseev) §

    这种情况只有在应用程序既有命名连接又有未命名连接时才会出现。

  • 改进 psqlCOPY\copy 选项的 Tab 补全 (Atsushi Torikoshi) §

    COPY FROMCOPY TO 提供了相同的补全建议, 尽管某些选项仅对其中一种情况有效。区分这些情况以提供更准确的建议。

  • 避免在 pgbench 接收多个流水线同步消息时的断言失败 (Fujii Masao) §

  • 确保 pg_dump 以有效的顺序导出域约束上的注释 (Jian He) §

    在某些情况下,注释命令可能出现在约束创建之前。

  • 确保 pg_dump 对所有类型的数据库对象具有稳定的排序顺序 (Noah Misch、Andreas Karlsson) § § §

    pg_dump 在执行依赖驱动的重排序之前,先按逻辑名称对对象进行排序。 此排序未考虑某些对象类型(如规则和约束)的完整唯一键,因此可能对逻辑上相同的数据库产生不同的排序顺序。 这使得通过 diff 比较 pg_dump 输出来比较数据库变得困难, 因此改进了逻辑以确保在所有情况下都有稳定的排序顺序。

  • pg_upgrade 中,检查不一致的继承非空约束 (Ali Akbar) § § § §

    18 之前的 PostgreSQL 版本允许删除继承列的非空约束。 然而,这会导致无法恢复的模式,从而导致 pg_upgrade 失败。 在 pg_upgrade 的预检查中检测此类情况,以允许用户在启动升级之前修复它们。

  • 避免在 initdb 期间启用 track_commit_timestamp 时的断言失败 (Hayato Kuroda、Andy Fan) §

  • 修复 pg_waldump 以显示 PREPARE TRANSACTION WAL 记录中关于已删除统计信息的信息 (Daniil Davydov) §

  • 避免在 contrib/dblink 建立连接期间可能的打开连接泄漏 (Tom Lane) §

    在将新连接对象插入 dblink 的哈希表时遇到内存不足的罕见情况下, 打开的连接将泄漏直到会话结束,在远程服务器上留下一个空闲会话。

  • 使 contrib/pg_prewarm 能够处理非常大的 shared_buffers 设置 (Daria Shanina) §

    shared_buffers 大于约 5000 万个缓冲区(400GB)时, 自动预热会因内存分配错误而失败。

  • contrib/pg_stat_statements 中,避免在规范化查询中使用的参数编号出现间隔 (Sami Imseih) §

  • 修复 contrib/postgres_fdw 的 DirectModify 方法中的内存泄漏 (Tom Lane) §

    如果查询在 DirectModify 方法的调用之间失败(当有 RETURNING 数据需要处理时可能发生), 持有远程修改命令结果的 PGresult 将在会话的剩余时间内泄漏。

  • 确保在 configure--with-includes--with-libraries 选项中列出的目录优先于系统提供的目录被搜索 (Tom Lane) §

    使用这些选项的一个常见原因是允许用户自行编译的库版本覆盖系统提供的版本。 然而,由于 makefile 中发出的命令中开关顺序不当,这在某些环境中无法工作。

  • 修复 configure__cpuid()__cpuidex() 的检测 (Lukas Fittl、Michael Paquier) §

    configure 未能检测到这些 Windows 特有的函数, 因此它们不会被使用,导致 CRC 计算速度较慢,因为无法验证硬件指令的可用性。 此错误的实际影响有限,因为 Windows 的生产构建通常不使用 Autoconf 工具链。

  • 修复在基于 Solaris 的平台上使用 --with-pam 选项时的构建失败 (Tom Lane) §

    Solaris 在 PAM 认证的 API 方面与其他 Unix 平台不一致。 这表现为 inconsistent pointer 编译器警告,我们以前从未处理过。 但从 GCC 14 开始,默认情况下这是一个错误而不是警告,因此对其进行修复。

  • 使我们的代码可移植到 GNU Hurd (Michael Banck、Christoph Berg、Samuel Thibault) § §

    修复关于 IOV_MAXO_RDONLY 的假设,这些假设在 Hurd 上不成立。

  • 使我们对 memset_s() 的使用严格符合 C11 标准 (Tom Lane) § §

    这避免了在某些平台上的编译失败。

  • 消除使用 Meson 和 MSVC 构建时的兼容性警告 (Peter Eisentraut) §

  • 防止 JSONB 比较代码中的未初始化值编译器警告 (Tom Lane) §

  • 避免使用 libxml2 2.14 及更高版本构建时的弃用警告 (Michael Paquier) §

  • 避免在 C++ 下编译 pg_locale.h 时出现问题 (John Naylor) §

    PostgreSQL 头文件通常需要 包装在 extern "C" { ... } 中才能被 C++ 编写的扩展所包含。 由于 pg_locale.h 使用了 libicu 头文件,这对其不起作用, 但我们可以通过在这些头文件中抑制仅限 C++ 的声明来解决此问题。 想要使用 libicu 的 C++ API 的 C++ 扩展可以通过在 pg_locale.h 之前包含 libicu 头文件来实现。