发布日期:. 2024-11-14
本次发布包含自 17.0 以来的多项修复。 有关 17 主版本中新特性的更多信息,请参见 Section E.10。
对于运行 17.X 的用户,无需执行转储/恢复。
不过,如果你曾经从一个引用另一分区表的分区表中分离过某个分区,并且之后没有删除该分区,那么你可能需要修复系统目录和/或数据损坏,详见下文第五条变更记录。
此外,在一种不常见的情况下,如果某个数据库的 LC_CTYPE 设置为 C,而 LC_COLLATE 设置为其他 locale,则文本列上的索引应按下文第六条变更记录所述重新建立索引。
当 RLS 作用于非顶层表引用时,确保缓存计划会被标记为依赖调用角色(Nathan Bossart) §
如果查询中的 CTE、子查询、sublink、security invoker 视图或 coercion projection 引用了带有行级安全策略的表,我们此前忽略了将所得计划标记为可能依赖执行它的角色。这可能导致同一会话后续执行查询时使用错误的计划,从而返回本应被隐藏的行,或隐藏本应返回的行。
PostgreSQL 项目感谢 Wolfgang Walther 报告此问题。 (CVE-2024-10976)
让 libpq 丢弃在 SSL 或 GSS 协议协商期间收到的错误消息(Jacob Champion) §
在加密协商完成之前收到的错误消息,可能是中间人注入的,而不是真实的服务器输出。报告这种消息会为各种安全隐患打开大门;例如,该消息可能伪装成查询结果,而粗心的用户会误以为那是正确输出。最佳做法似乎是丢弃这类数据,只依赖 libpq 自己对连接失败的报告。
PostgreSQL 项目感谢 Jacob Champion 报告此问题。 (CVE-2024-10977)
修复 SET SESSION AUTHORIZATION 与 SET ROLE 之间的非预期交互(Tom Lane) § §
SQL 标准要求 SET SESSION AUTHORIZATION 具有执行 SET ROLE NONE 的副作用。我们的实现存在缺陷,使这两个设置之间的交互比预期更多。尤其是,回滚一个执行过 SET SESSION AUTHORIZATION 的事务时,即使 ROLE 之前并不是 NONE,也会把它还原为 NONE,从而导致当前有效用户 ID 与事务之前可能不同。在函数的 SET 子句中临时设置 session_authorization 也会产生类似效果。另一个相关 bug 是,如果并行工作进程检查 current_setting('role'),它即便本应看到别的值,也会看到 none。
PostgreSQL 项目感谢 Tom Lane 报告此问题。 (CVE-2024-10978)
防止受信任的 PL/Perl 代码修改环境变量(Andrew Dunstan、Noah Misch) § § §
操作进程环境变量(例如 PATH)的能力会给攻击者带来执行任意代码的机会。因此,“trusted” PL 不得提供这种能力。为修复 plperl,我们将 %ENV 替换为一个 tied hash,任何修改尝试都会被拒绝并给出警告。不受信任的 plperlu 仍保留修改环境的能力。
PostgreSQL 项目感谢 Coby Abrams 报告此问题。 (CVE-2024-10979)
修复在附加或分离表分区时,对外键约束系统目录状态的更新问题(Jehan-Guillaume de Rorthais、Tender Wang、Álvaro Herrera) § §
如果被引用表是分区表,那么对于引用方表来说,独立表与分区表所需的系统目录条目并不相同。ATTACH/DETACH PARTITION 命令未能正确执行这一转换。尤其是,在 DETACH 之后,如今已独立的表会缺少外键强制触发器,从而可能导致该表之后包含违反外键约束的行。后续再次 ATTACH 也可能以令人意外的错误失败。
修复方法是,对如今已独立的表上的每个有问题约束执行 ALTER TABLE DROP CONSTRAINT,然后重新添加该约束。如果重新添加失败,说明已有错误数据混入。你需要手工重新建立引用表与被引用表之间的一致性,然后再添加该约束。
可使用以下查询识别损坏的约束,并构造重建它们所需的命令:
SELECT conrelid::pg_catalog.regclass AS "constrained table",
conname AS constraint,
confrelid::pg_catalog.regclass AS "references",
pg_catalog.format('ALTER TABLE %s DROP CONSTRAINT %I;',
conrelid::pg_catalog.regclass, conname) AS "drop",
pg_catalog.format('ALTER TABLE %s ADD CONSTRAINT %I %s;',
conrelid::pg_catalog.regclass, conname,
pg_catalog.pg_get_constraintdef(oid)) AS "add"
FROM pg_catalog.pg_constraint c
WHERE contype = 'f' AND conparentid = 0 AND
(SELECT count(*) FROM pg_catalog.pg_constraint c2
WHERE c2.conparentid = c.oid) <>
((SELECT count(*) FROM pg_catalog.pg_inherits i
WHERE (i.inhparent = c.conrelid OR i.inhparent = c.confrelid) AND
EXISTS (SELECT 1 FROM pg_catalog.pg_partitioned_table
WHERE partrelid = i.inhparent)) +
CASE WHEN pg_catalog.pg_partition_root(conrelid) = confrelid THEN
(SELECT count(*) FROM pg_catalog.pg_partition_tree(confrelid)
WHERE level = 1)
ELSE 0 END);
由于一个或多个 ADD CONSTRAINT 步骤可能失败,你应将该查询的输出保存到文件中,然后逐步尝试执行每一步。
修复当 LC_COLLATE 与 LC_CTYPE 不同时,对 C locale 的测试(Jeff Davis) §
当使用 libc 作为默认排序规则提供者时,用于测试排序是否使用了 C locale 的代码,误查了 LC_CTYPE 而不是 LC_COLLATE。在这两个设置相同的典型情况下,这不会造成影响;如果两者都不是 C(也不是其别名 POSIX),同样无影响。不过,如果 LC_CTYPE 是 C,而 LC_COLLATE 是其他 locale,就可能产生错误的查询结果,也可能导致字符串索引损坏。使用这类设置的数据库用户应在安装本次更新后对受影响的索引重新建立索引。反过来,如果 LC_COLLATE 是 C 而 LC_CTYPE 是其他 locale,则会导致性能下降,但不会产生实际错误。
如果查询中键列的排序规则与分区键的排序规则不匹配,则不要使用分区连接或分区聚合(Jian He、Webbo Han) § §
这类计划可能产生错误结果。
避免在将 NOT NULL 列上的 IS NULL 测试转换为常量 FALSE 后发生规划器失败(Richard Guo) §
这个 bug 通常会导致诸如 “variable not found in subplan target lists” 之类的错误。
避免在内联某个参数包含特定数组相关结构的 SQL 函数时,规划器可能崩溃(Tom Lane、Nathan Bossart) §
修复 MERGE ... WHEN NOT MATCHED BY SOURCE 动作可能产生错误结果或 “wrong varnullingrels” 规划器错误的问题(Dean Rasheed) § §
修复当某个 UNION ALL 成员查询的输出需要排序且排序列是表达式时,可能出现 “could not find pathkey item to sort” 错误的问题(Andrei Lepikhov、Tom Lane) §
修复 B-tree ScalarArrayOp 索引扫描中的边界情形问题(Peter Geoghegan) §
当带有这类计划的可滚动游标回退到起点后再向前执行时,可能出现错误结果。
修复在 query 被 DO INSTEAD NOTIFY 规则重写时,COPY ( 可能出现断言失败或令人困惑错误消息的问题(Tender Wang、Tom Lane) §query) TO ...
修复对 COPY 的 FORCE_NOT_NULL 和 FORCE_NULL 选项的校验(Joel Jacobson) §
某些不正确的用法现在会像预期那样被拒绝。
修复当 json_objectagg() 调用包含 volatile 函数时的服务器崩溃(Amit Langote) §
修复并行哈希连接期间对倾斜数据的检测(Thomas Munro) §
当哈希连接内侧的一处分区积累了过多元组而被重新分区后,我们会检查该分区的全部元组是否都进入了同一个子分区,这表明它们可能具有相同的哈希值,继续重新分区也无济于事。在某些情况下,这项检查会失效,导致系统反复进行徒劳的重新分区,最终以资源耗尽错误收场。
避免在使用 ALTER DATABASE SET 设置需要基于 search_path 查找的服务器参数时崩溃,例如 default_text_search_config(Jeff Davis) §
避免在分区表上创建新索引时重复查找 opclass 和 collation(Tom Lane) §
之所以成问题,主要是因为其中一些查找会在受限的 search_path 下进行,从而导致当 CREATE INDEX 命令引用 pg_catalog 之外的对象时出现意外失败。
此修复还阻止了父分区索引上的注释被复制到子索引。
为分区表补上到 CREATE TABLE ... USING 中指定的非内建访问方法的缺失依赖(Michael Paquier) §
当存在依赖于某访问方法的表时,删除该访问方法本应被阻止,但此前并未如此,因而允许后续出现异常行为。注意,此修复只会防止本次更新之后新建的分区表出现这类问题。
不允许使用包含非 ASCII 字符的 locale 名称(Thomas Munro) §
这只会在 Windows 上成为问题,因为其他地方不会使用这种 locale 名称。之所以有问题,是因为这类名称究竟使用什么编码表示并不清楚,毕竟 locale 自身定义了要使用的编码。在近期的 PostgreSQL 版本中,由于对此产生混淆,Windows 运行时库可能会触发 abort。
任何遇到这一新错误消息的人,都应使用 Windows Locale Builder 创建一个仅含 ASCII 名称的新复制 locale,或者考虑改用符合 BCP 47 的 locale 名称,例如 tr-TR。
修复提交可串行化事务时的竞争条件(Heikki Linnakangas) §
对刚刚提交事务的错误处理,可能导致断言失败或出现 “could not access status of transaction” 错误。
修复 COMMIT PREPARED 中导致 2PC 文件遗留的竞争条件(wuchengwen) §
并发执行的 PREPARE TRANSACTION 可能导致 COMMIT PREPARED 未能删除已完成事务的磁盘两阶段状态文件。虽然这不会立刻造成不良影响,但随后的崩溃恢复可能会因 “could not access status of transaction” 失败,并需要手工删除该遗留文件才能恢复服务。
避免在 VACUUM FULL 期间跳过无效 toast 索引后发生无效内存访问(Tender Wang) §
在这条代码路径中,用于跟踪尚待重建索引的列表未被正确更新,从而给后续带来断言失败或崩溃风险。
修复 “in place” 系统目录更新可能丢失的几种情形(Noah Misch) § § § § § § §
普通的行更新会写入该行的新版本,以保留事务可回滚的能力。然而,某些系统目录更新有意设计为非事务性的,并且会对该行执行原地更新。这些补丁修复了可能导致原地更新效果丢失的竞争条件。举例来说,系统可能会忘记已将 pg_class.relhasindex 设为 true,从而阻止新索引被更新,并最终导致索引损坏。
在恢复结束时重置系统目录缓存(Noah Misch) §
这可以防止因使用系统目录缓存中的陈旧数据,而导致原地系统目录更新丢失的情况。
在禁止处理中断期间避免使用并行查询(Francesco Degrassi、Noah Misch、Tom Lane) § §
这种情况在正常使用中不会出现,但在某些测试场景下可以触发,例如把 SQL 语言函数用作 B-tree 支持函数(这在生产环境中会慢得无法接受)。如果真的发生,就会导致无限期等待。
在 pg_cursors 视图中忽略尚未定义的 Portal(Tom Lane) §
在新游标建立过程中,可能会调用检查该视图的用户自定义代码;一旦如此,就可能发生空指针解引用。现通过让该视图排除尚未完全建立的游标来避免此问题。
避免在解码涉及插入列默认值的事务时,出现 “unexpected table_index_fetch_tuple call during logical decoding” 错误(Takeshi Ideriha、Hou Zhijie) § §
降低逻辑解码的内存消耗(Masahiko Sawada) §
使用更小的默认块大小来存储逻辑复制期间接收到的元组数据。这可以减少内存浪费,据报告在处理长事务时浪费非常严重,甚至会导致内存耗尽失败。
修复当 CALL 位于 PL/pgSQL EXCEPTION 块中时,从其参数列表调用 stable 函数的行为(Tom Lane) §
与我们先前季度发布中的类似修复一样,这种情况会让这些函数拿到错误的快照,从而看到自外层事务开始以来已被修改行的陈旧值。
按与其他整型选项相同的方式解析 libpq 的 keepalives 连接选项(Yuto Sasaki) §
这里的代码与其他情形不同,会拒绝选项值中的尾随空白字符。事实证明,这在 ecpg 的使用场景中会造成问题。
在 ecpglib 中,修复解析错误 datetime 输入时发生的越界读取(Bruce Momjian、Pavel Nekrasov) §
代码可能尝试读取常量数组起始位置之前的地址。不过,从现实影响看,后果似乎较小。
修复 psql 的 describe 命令,使其重新能够与 9.4 之前的服务器协同工作(Tom Lane) §
由于使用了这些旧版本中不存在的函数,涉及显示 ACL(权限)列的命令在非常旧的 PostgreSQL 服务器上会失败。
避免在 psql 的 \watch 命令中指定小于 1ms 的间隔时发生挂起(Andrey Borodin、Michael Paquier) §
现在会将其视为与零间隔相同,也就是两次执行之间不等待。
修复无法在 ~/.pgpass 中找到复制密码的问题(Tom Lane) §
如果未提供 -d 或 --dbname 开关,pg_basebackup 和 pg_receivewal 就无法匹配 ~/.pgpass 中数据库名字段为 replication 的条目,从而导致意外弹出密码提示。
在 pg_combinebackup 中,如果本应包含完整备份的目录里出现增量备份文件,则抛出错误(Robert Haas) §
在 pg_combinebackup 中,不要构造包含双斜杠的文件名(Robert Haas) §
这不会造成功能性问题,但双斜杠会出现在错误消息中,从而引起混淆。
避免在 vacuumdb 和并行 reindexdb 中尝试重建临时表和临时索引(VaibhaveS、Michael Paquier、Fujii Masao、Nathan Bossart) § § §
重建其他会话的临时表不可能成功,但某些代码路径中缺少跳过它们的检查,从而导致了不必要的失败。
修复 ARM64 平台上 LLVM 生成代码不正确的问题(Thomas Munro、Anthonin Bonnefoy) §
在 ARM 平台上使用 JIT 编译时,生成的代码无法支持超过 32 位的重定位距离,因此如果生成代码被不走运地放置到某些位置,就可能在大内存系统上导致服务器崩溃。
修复若干处错误假定进程启动时间(以 time_t 表示)能够装入 long 值的地方(Max Johnson、Nathan Bossart) §
在 long 为 32 位的平台上,尤其是 Windows,这种写法会在 Y2038 之后失效。大多数故障似乎只是表面上的,但值得注意的是,pg_ctl start 会挂起。
将时区数据文件更新到 tzdata 2024b(Tom Lane) § §
此次 tzdata 发布把旧的 System-V 兼容时区名改成对应地理时区的副本;例如,PST8PDT 现在成了 America/Los_Angeles 的别名。最主要的可见后果是:对于标准化时区引入之前的时间戳,该时区会被视为代表对应地点的地方平太阳时。比如,在 PST8PDT 中,timestamptz 输入 1801-01-01 00:00 以前会被渲染为 1801-01-01 00:00:00-08,现在则会被渲染为 1801-01-01 00:00:00-07:52:58。
此外,还包含对墨西哥、蒙古和葡萄牙的历史修正。尤其是,Asia/Choibalsan 现在成为 Asia/Ulaanbaatar 的别名,而不再是独立时区,主要因为人们发现这两个时区之间的差异依据的是不可靠的数据。
如果您发现文档中有不正确的内容、与您使用特定功能的经验不符或需要进一步说明,请使用此表单来报告文档问题。