E.19. 发布版本 12.4 #
发布日期:. 2020-08-13
本次发布包含来自 12.3 的多项修复。有关 12 主版本新特性的说明,请参见第 E.23 节。
E.19.2. 变更
在逻辑复制 WAL 发送进程和应用工作进程中设置安全的
search_path(Noah Misch)§ §发布者或订阅者数据库中的恶意用户,都可能导致以运行复制的角色身份执行任意 SQL 代码,而该角色通常是超级用户。这里的一部分风险与 CVE-2018-1058 中所述的风险相同,本补丁通过确保复制发送进程和接收进程以空的
search_path设置运行来缓解这些风险。(与 CVE-2018-1058 一样,这一改动可能使被复制表的 DDL 中未充分限定的名称出现问题。)其他风险则是复制不可信角色所属对象所固有的;我们最多只能在文档中说明存在需要考虑的风险。(CVE-2020-14349)提高 contrib 模块安装脚本的安全性(Tom Lane)§
如果攻击者能够在扩展的目标模式或某个前置扩展的模式中创建对象,就可以针对扩展安装脚本实施与 CVE-2018-1058 中所述类似的攻击。由于安装扩展通常需要超级用户权限,这可能成为获取超级用户权限的一条途径。为缓解这一风险,更谨慎地设置运行安装脚本时使用的
search_path;在脚本中禁用check_function_bodies;并修正一些 contrib 模块中用于调整系统目录的查询,确保它们安全。同时提供文档,帮助第三方扩展作者编写安全的安装脚本。这并不是完整的解决方案;如果安装时不够谨慎,依赖其他扩展的扩展仍可能面临风险。(CVE-2020-14350)修复分区剪枝中的边界情况(Etsuro Fujita,Dmitry Dolgov)§ §
存在多个分区键列时,如果某些列没有用于约束它们的
WHERE子句,或具有多个约束子句,剪枝测试的生成就可能行为异常。这可能导致服务器崩溃、错误的查询结果或断言失败。修复逐分区嵌套循环连接内侧的参数化 BitmapAnd 和 BitmapOr 索引扫描的构建(Tom Lane)§
如果计划中的这种扫描需要使用连接外侧的值,通常会在执行时崩溃。
修复同一查询对分区表同时进行静态和运行时分区剪枝,且添加新分区与查询并发进行时不正确的计划执行(Amit Langote,Tom Lane)§
在逻辑复制 WAL 发送进程中,修复发送保活消息后未能发送反馈消息的问题(Álvaro Herrera)§
使用内置逻辑复制时,这个问题相对较小,因为内置 WAL 接收进程本来就会相当频繁地发送反馈回复(从而清除错误状态)。但对于 pglogical 等其他复制系统,它会造成显著的性能问题。
修复逻辑复制订阅者中特定列
UPDATE触发器的触发(Tom Lane)§代码忽略了发布者和订阅者的表中列编号可能不同的情况,因此如果列编号确实不同,就可能错误判断应触发哪些触发器。
在
pg_replication_slot_advance()期间更新最旧的 xmin 和 LSN 值(Michael Paquier)§此函数以前未能这样做,可能导致手动推进复制槽后无法清理资源(例如移除不再需要的 WAL 段)。
修复
ts_headline()执行缓慢的问题(Tom Lane)§上一批小版本中添加的短语搜索修复,可能使
ts_headline()处理长文档时耗费极不合理的时间;更糟的是,在出现问题的循环中无法取消查询。确保
repeat()函数可以被查询取消中断(Joe Conway)§修复
pg_current_logfile(),使其结果在 Windows 上不包含回车符(\r)(Tom Lane)§确保
pg_read_file()及相关函数一直读取到 EOF(Joe Conway)§ §以前,如果未给出要读取的具体数据长度,这些函数就会在读到
stat()报告的文件长度时停止。这对管道和其他虚拟文件并不适用。禁止在
jsonpath计算中使用数值NaN(Alexander Korotkov)§SQL 和 JSON 都没有
NaN(非数值)的概念,但jsonpath代码仍尝试允许此类值。这必然导致非标准行为,因此似乎最好从一开始就拒绝此类值。在浮点聚合中正确处理单个
Inf或NaN输入(Tom Lane)§受影响的聚合为
corr()、covar_pop()、regr_intercept()、regr_r2()、regr_slope()、regr_sxx()、regr_sxy()、regr_syy()、stddev_pop()和var_pop()。此类情况下,正确结果应为NaN,但 PostgreSQL v12 引入的一项算法修改使这些聚合产生了零。修复对
numeric类型列进行并行聚合时对NaN输入的错误处理(Tom Lane)§如果某些部分聚合工作进程只找到
NaN,而其他工作进程只找到非NaN值,结果就会被错误合并,可能导致整体结果错误(即本应为NaN时却不是)。拒绝大于 24 小时的日内时间值(Tom Lane)§
日期时间输入代码的本意是允许“24:00:00”或等价的“23:59:60”,但不允许更大的值。然而,范围检查的代码有误,会接受“23:59:60.
nnn”,其中小数秒nnn可以非零。对于时间戳值,这会使其跨入下一天的第一秒。对于time和timetz值,存储的值实际上会超过 24 小时,从而导致转储/重载失败,并可能引发其他异常行为。撤销
EXPLAIN非文本输出格式中为索引名称添加双引号的行为(Tom Lane,Euler Taveira)§修复
EXPLAIN对使用Gather Merge节点的计划中并行工作进程的资源使用统计,尤其是缓冲区访问统计(Jehan-Guillaume de Rorthais)§修复
ALTER TABLE中重新验证约束的时机(David Rowley)§如果
ALTER TABLE需要完全重写表内容(例如更改列的数据类型),又需要扫描表以重新验证外键或CHECK约束,有时会按错误顺序执行,导致“could not read block 0 in file "base/nnnnn/nnnnn": read only 0 of 8192 bytes”等奇怪错误。修复
REINDEX CONCURRENTLY,使其保留索引的复制标识标志(Michael Paquier)§以前,重建表的复制标识索引会导致这一设置丢失,使之后的逻辑解码输出无法包含旧元组值。
规避
pg_subscription.subslotname和pg_subscription_rel.srsublsn上不正确的非空标记(Tom Lane)§ §引导目录数据错误地将这两个目录列标记为始终非空。在现有安装实例中不容易修正这一错误(不过 v13 及更新版本将具有正确标记)。主要依赖该标记正确性的地方是启用 JIT 的元组解构,因此让它显式忽略这两列的标记。另外,调整某些未检查是否为空就访问
srsublsn的 C 代码;由此引发崩溃的可能性很低,但或许并非不可能。处理附加到
FROM子句中未扁平化的子SELECT上的限制子句里的LATERAL引用(Tom Lane)§这一疏漏可能导致查询执行时断言失败或崩溃。
为选择率估计期间调用的操作符使用查询指定的排序规则(Tom Lane)§ §
以前使用底层数据库列的排序规则,但使用查询的排序规则可以说更为正确。更重要的是,既然现在已有非确定性排序规则,某些操作符在传入非确定性排序规则时会直接失败。我们不希望查询本身可以执行时,规划却失败,因此出于估计目的调用操作符时,必须使用查询的排序规则。
避免认为从未分析过的外部表具有零个元组(Tom Lane)§
这主要影响规划器对
GROUP BY将产生的分组数量的估计。移除 BRIN 索引取消汇总过程中关于“leftover placeholder tuple”的错误警告(Álvaro Herrera)§
取消清理后,这种情况可以正常出现,因此对此发出警告会产生过多噪声。
修复“共享文件集”临时文件的表空间选择(Magnus Hagander,Tom Lane)§ §
如果
temp_tablespaces为空,或显式指定数据库的主表空间,这些文件会被放到pg_default表空间,而非预期的数据库主表空间。修复 WAL 一致性检查期间屏蔽 SP-GiST 索引页面内容时的边界情况错误(Alexander Korotkov)§
启用
wal_consistency_checking时,这可能导致错误的失败报告。改进服务器
buffile模块中的错误处理(Thomas Munro)§ §修复某些无法区分 I/O 错误与到达 EOF,或完全未报告 I/O 错误的情况。另外,在适当位置增加块号、字节数等详细信息。
修复
SERIALIZABLE隔离模式中的冲突检查异常(Peter Geoghegan)§如果一个并发插入的元组被另一个并发事务更新,且两个元组版本对当前事务的快照都不可见,序列化冲突检查就可能错误判断该元组是否与当前事务的结果有关。这可能允许本应因序列化错误而失败的可序列化事务提交。
避免将已失效的 B-树索引条目反复标记为失效(Masahiko Sawada)§
虽然功能上无害,但在启用了校验和或
wal_log_hints时,这会产生无用的 WAL 流量。修复检查点进程,使其在
fsync关闭时丢弃文件同步请求(Heikki Linnakangas)§fsync关闭时,这些请求被视为不执行任何操作,但我们忘记从检查点进程的待处理操作表中移除它们。这会导致该表膨胀,并且如果之后重新启用fsync,还可能出现断言失败。修复某些代码路径修改
pg_control前未获取正确锁的问题(Nathan Bossart,Fujii Masao)§这一疏漏可能使
pg_control以不一致的校验和写出,导致之后出现问题,包括在下次pg_control更新之前崩溃时无法重启数据库。修复
currtid()和currtid2()中的错误(Michael Paquier)§ §这些函数没有文档记录,且仅由很早版本的 ODBC 驱动使用。它们包含编码错误,可能导致崩溃,或在应用于没有存储的关系时产生“could not open file”等令人困惑的错误消息。
避免持有自旋锁时调用
elog()或palloc()(Michael Paquier,Tom Lane)§ §复制槽相关逻辑有几处违反了这一编码规则。虽然出现问题的可能性很低,但被调用函数一旦出错,就会导致自旋锁卡住。
修复逻辑复制订阅者中的断言,以允许使用
REPLICA IDENTITY FULL(Euler Taveira)§这只是一个不正确的断言,因此不影响标准的生产构建。
确保 libpq 在写入失败后继续尝试从数据库连接套接字读取(Tom Lane)§
这不仅是为了确保收集即将终止的服务器进程发出的最后错误消息,还因为我们只有看到读取失败才会认定连接丢失。这一疏漏使 libpq 在传输中途失去连接后,仍无限期尝试发送
COPY数据,而不向应用报告失败。修复 libpq 管理 GSS 加密状态时的缺陷(Tom Lane)§
使用 GSS 加密的连接,在服务器重启后尝试重置连接,或转而尝试候选服务器列表中的下一台服务器时,可能卡死。
修复 ecpg 使用
bytea和游标变量时的崩溃(Jehan-Guillaume de Rorthais)§在 pg_dump 和 pg_basebackup 中正确报告磁盘空间不足错误(Justin Pryzby,Tom Lane,Álvaro Herrera)§
某些代码路径可能产生“could not write file: Success”之类不合理的报告。
使 pg_restore 在需要乱序恢复数据项时,能够处理没有数据偏移量的自定义格式归档文件(David Gilman,Tom Lane)§ §
如果无法对输出进行定位(例如输出被通过管道传给其他程序),pg_dump 就会生成此类文件。此修复主要改进了从此类文件进行并行恢复的能力。
修复同时具有表级权限和逐列权限的表的并行恢复(Tom Lane)§
必须先应用表级权限授予,但并行恢复未能可靠地保证这一顺序,可能导致“tuple concurrently updated”错误,或丢失某些逐列权限授予。修复方式是在归档文件中为这些条目添加依赖链接,因此必须使用修正后的 pg_dump 重新转储,才能确保问题不再发生。
确保 pg_upgrade 运行时,将目标集群中的
vacuum_defer_cleanup_age设为零(Bruce Momjian)§如果目标集群的配置已将
vacuum_defer_cleanup_age设为非零值,就会使系统目录的冻结无法正常进行,进而使升级以令人困惑的方式失败。现在确保在升级期间覆盖此类设置。修复 pg_recvlogical,使其在退出前读取完待处理消息(Noah Misch)§ §
否则,复制发送进程可能检测到发送失败并退出,而未对复制槽的 LSN 位置进行预期的最终更新。这会导致下次连接后重新传输数据。另外,还可能遗漏在 pg_recvlogical 想要消费的最后一条数据之后发送的错误消息。
修复 pg_rewind 对源数据目录中刚删除的文件的处理(Justin Pryzby,Michael Paquier)§
使用在线源数据库时,可能发生并发文件删除;但如果删除发生在看到文件目录项与使用
stat()检查它之间,pg_rewind 就会处理失当。使 pg_test_fsync 在 Windows 上使用二进制 I/O 模式(Michael Paquier)§
以前,它以文本模式写入测试文件,无法准确反映 PostgreSQL 的实际用法。
修复
contrib/amcheck,使其不再因已删除的索引页为空而报错(Alexander Korotkov)§这种状态在 WAL 重放期间是正常的。
修复
contrib/dblink未能正确初始化本地状态的问题(Joe Conway)§在特定条件组合下,这可能导致
dblink_close()发出意外的远程COMMIT。修复
contrib/pgcrypto对deflate()的错误使用(Tom Lane)§由于未正确遵循 zlib 的 API 要求,
pgp_sym_encrypt函数可能产生不正确的压缩数据。尚未收到使用原版 zlib 时出现此错误的报告,但使用 IBM 的 zlibNX 实现时可以观察到。修复
contrib/pgcrypto的pgp_sym_decrypt函数中解压缩逻辑的边界情况(Kyotaro Horiguchi,Michael Paquier)§压缩流可以合法地以空包结束,但解压缩器未能处理这种情况,并会报告数据损坏。
支持使用 Microsoft Visual Studio 2015 及更新版本构建我们的 NLS 代码(Juan José Santamaría Flecha,Davinder Singh,Amit Kapila)§
避免源代码树上方数级目录中存在名为
configure的文件时,MSVC 安装脚本可能发生的失败(Arnold Müller)§这可能使通过查找
configure来识别源代码树顶层的某些逻辑产生混淆。