2025年9月25日: PostgreSQL 18 发布!

PostgreSQL 周报 - 2021 年 2 月 28 日

发布于 2021-03-01,作者:PWN
PWN

PostgreSQL 周报 - 2021 年 2 月 28 日

Database Lab 2.2.1 发布,这是一个用于快速克隆大型 PostgreSQL 数据库以构建非生产环境的工具:https://gitlab.com/postgres-ai/database-lab/-/releases

dbMigration .NET v13.4 发布,这是一个数据库迁移和同步工具。https://fishcodelib.com/DBMigration.htm

Joe 0.9.0 发布,这是一个 Slack 聊天机器人,可帮助后端开发人员和 DBA 诊断和优化 PostgreSQL 查询。https://gitlab.com/postgres-ai/joe/-/releases#0.9.0

pgAdmin4 5.0 发布,这是 PostgreSQL 的 Web 和原生 GUI 控制中心。https://www.pgadmin.org/docs/pgadmin4/5.0/release_notes_5_0.html

pgagroal 1.2.0 发布,这是 PostgreSQL 的高性能协议原生连接池。https://agroal.github.io/pgagroal/release/announcement/2021/02/23/pgagroal-1.2.0.html

本周人物:https://postgresql.life/post/takayuki_tsunakawa/

PostgreSQL 产品新闻

二月 PostgreSQL 作业

https://archives.postgresql.org/pgsql-jobs/2021-02/

PostgreSQL 相关新闻

Planet PostgreSQL:https://planet.postgresql.org/

本周 PostgreSQL 周报由 David Fetter 提供。

请在太平洋标准时间(PST8PDT)周日晚上3:00之前将新闻和公告发送至 david@fetter.org。

已应用补丁

Tom Lane 提交

  • 修复 trgm_regexp.c 中的无效数组访问。08c0d6ad6 中的一个“纸上谈兵”的 bug:我遗漏了一个需要防御 RAINBOW 颜色值的数组访问。令人惊讶的是,除了 buildfarm 成员 thorntail 之外,没有任何人注意到这个无效的数组访问。感谢 Noah Misch 的协助排查此问题。https://git.postgresql.org/pg/commitdiff/6ee479abfc27a18c37fe77140d16d3ac31f4ac31

  • 稍微简化了 DFA 的内存管理。Coverity 抱怨 regexec.c 中的函数可能会泄露 DFA 存储。它错了,但这个逻辑足够混乱,以至于 Coverity 无法理解它并不令人意外。重写代码,希望能让其对人类和机器都更易读。https://git.postgresql.org/pg/commitdiff/190c79884aae540c92f017701726ed69265e2dab

  • 抑制新正则表达式匹配所有检测代码中的编译器警告。gcc 10 足够智能,能够注意到控制流可能到达这个 "hasmatch[depth]" 赋值,其中 depth < 0,但它不够智能,无法知道这需要一个严重损坏的 NFA 图。将 assert() 更改为普通的运行时测试以关闭警告。根据 Andres Freund 的报告。讨论:https://postgr.es/m/20210223173437.b3ywijygsy6q42gq@alap3.anarazel.de https://git.postgresql.org/pg/commitdiff/3db05e76f92846d4b54d7de251b0875cf1e23aa4

  • 允许方括号内的字符类转义符取反。现在允许在方括号表达式中使用取反的字符类转义符 \D、\S、\W。这样做没有语义上的困难,但先前使用的基于宏展开的实现无法处理。此外,引入“word”作为允许的字符类名称,因此 "\w" 在方括号外现在等同于 "[[:alnum:]_]",在方括号内等同于 "[:word:]"。POSIX 允许此类实现特定的扩展,并且在 bash 等中也使用相同的名称。这引发了一个令人惊讶的兼容性问题:像 "[\w-_]" 这样的构造现在不再被允许,因为我们的文档一直说它们应该是:字符类不能是范围的端点。以前,因为 \w 只是 "[:alnum:]_" 的宏,所以这样的构造被读取为 "[[:alnum:]_-_]",因此只要 "-" 后面的字符在数值上大于或等于 "_",它就会被接受。在此过程中进行了一些实现清理:* 移除 lexnest() hack,并因此清理 wordchrs() 以免与词法分析器交互。* 修复 colorcomplement(),使其不至于在涉及的颜色数量上呈 O(N^2) 复杂度。* 移除 Brackpart() 中看似无用的、针对单字符字符元素名称的 element() 调用。element() 总是将它们映射为字符本身,如果不是这样的话,事情会非常糟糕——"[a]" 匹配的东西难道不应该与 "a" 不同吗?此外,brackpart() 中的快捷路径实际上并没有这样做,使其更加不一致。讨论:https://postgr.es/m/2845172.1613674385@sss.pgh.pa.us 讨论:https://postgr.es/m/3220564.1613859619@sss.pgh.pa.us https://git.postgresql.org/pg/commitdiff/2a0af7fe460eb46f9af996075972bf7c2e3f211d

  • 将正则表达式 \D 和 \W 的简写改为始终匹配换行符。Newline 肯定不是数字,也不是单词字符,所以它应该匹配这些取反的字符类是合乎情理的。以前,\D 和 \W 默认就是这样工作的,但在区分大小写的模式('n' 或 'p' 标志)下,它们不匹配换行符。这种行为以前是强制的,因为明确的取反字符类在区分大小写的模式下不匹配换行符;但从上一次提交开始,这个实现限制不再存在。改变这一点似乎很有用,因为区分大小写模式的主要实际用途似乎是匹配 Perl 和 Javascript 等其他正则表达式引擎的默认行为……而它们的默认行为是这些匹配换行符。通过编写明确的取反字符类,例如 [^[:digit:]] 或 [^[:word:]],可以保留旧的行为。(这意味着 \D 和 \W 并不完全等同于这些字符串,但它们本来也不是。)讨论:https://postgr.es/m/3220564.1613859619@sss.pgh.pa.us https://git.postgresql.org/pg/commitdiff/7dc13a0f0805a353cea0455ed95701322b39d4dd

  • 文档:删除 src/backend/regex/re_syntax.n。我们不将此文件作为文档发布,而且它的维护比 func.sgml 中的实际文档随意得多,所以让我们删除它。我认为我将其包含在提交 7bcc6d98f 中的唯一原因是因为 Berkeley 时代的源代码在该目录中有一个 man page。讨论:https://postgr.es/m/4099447.1614186542@sss.pgh.pa.us https://git.postgresql.org/pg/commitdiff/301ed8812e3f8b102b85e1f5a59e95990ed9a868

  • 修复 WITH RECURSIVE 处理中的列表操作 bug。makeDependencyGraphWalker 和 checkWellFormedRecursionWalker 认为它们可以在列表被递归调用修改时,持有指向列表第一个 cons 单元的指针。当 cons 单元实际被单独 palloc() 时,这是可以的……但自从 commit 1cff1b95a 以来,这非常不安全,会导致核心转储或关于 WITH 嵌套错误的错误报告。在实际应用中,这至少需要一个七层深的 WITH 嵌套才能引起问题,但启用 DEBUG_LIST_MEMORY_USAGE 可以使 bug 在嵌套深度较浅时出现。根据 Alexander Lakhin 的 bug #16801。回溯到 v13。Michael Paquier 和 Tom Lane 讨论:https://postgr.es/m/16801-393c7922143eaa4d@postgresql.org https://git.postgresql.org/pg/commitdiff/80ca8464fe02296c8efefd53746e6d6a3f456d1e

  • 改进正则表达式编译器中的内存管理。之前的逻辑为每个状态创建了一个独立的弧池,使得每个状态的出弧物理上存储在其中。也许这个选择是出于不想在每个弧中包含一个“from”指针的考虑;但 Spencer 早已放弃了这个想法,而且现在看不出它的价值。这种方法在内存消耗方面实际上是灾难性的。首先,由该引擎构建的 NFA 平均每个状态有大约 4 个弧,其中大多数只有一个或两个出弧。因此,为每个状态预分配 10 个出弧已经导致了双倍或更多的膨胀。更糟的是,NFA 优化阶段会随意移动弧。在一个大的 NFA 中,一些状态会有数百个出弧,所以到了优化阶段的后期,我们会发现大量的状态的弧池为每个状态都留有数百个弧的空间,即使其中只有几个弧在使用。我们在实际的正则表达式中看到过,这种情况会将内存需求膨胀 25 倍甚至更多。因此,用整个 NFA 的单个弧池替换每个状态的弧池,并使用可变大小的分配批次而不是一次分配 10 个。顺便,我们也批处理状态结构体的分配,以进一步减少 malloc 的流量。这偶然地允许 moveouts() 以与 moveins() 类似的方式进行优化:当将弧移动到另一个状态时,现在可以将相同的弧结构体重新链接到不同的出链中,而在之前,代码不变量要求我们创建一个物理上的新弧然后释放旧的。这些更改将正则表达式编译器对平均大小正则表达式的典型空间消耗减少了大约一半,对于大型或复杂的正则表达式则减少得多。在一个大型的实际正则表达式测试集中,我们以前有大约六个案例因超过 REG_MAX_COMPILE_SPACE 限制(约 150MB)而因“正则表达式过于复杂”而失败;我们需要将该限制提高到接近 400MB 才能让它们在旧代码下工作。现在,其中没有任何案例需要超过 13MB 的编译空间。此外,由于 malloc 流量的减少,整个测试集的运行速度提高了约 10%。讨论:https://postgr.es/m/168861.1614298592@sss.pgh.pa.us https://git.postgresql.org/pg/commitdiff/0fc1af174cf7113445e116feb2813405b838a47d

  • 文档:进一步澄清 libpq 关于连接字符串 URI 的描述。将概要分解为命名部分,使其不那么混乱。稍微应用 SGML 标记。对附近的文本进行一些复制编辑。概要的修改由 Alvaro Herrera 和 Paul Förster 完成,其余部分由我负责。回溯到 v10,那里出现了多主机连接字符串。讨论:https://postgr.es/m/6E752D6B-487C-463E-B6E2-C32E7FB007EA@gmail.com https://git.postgresql.org/pg/commitdiff/4e90052c46c7751779ed83627676ed5e74ebe6d4

Thomas Munro 推送

Michaël Paquier 提交

Peter Eisentraut 提交

Fujii Masao 提交

Magnus Hagander 已推送

  • 修复网站样式文档构建。使用 STYLE=website 构建文档时,引用了一个不再存在于网站上的样式表,因为我们将其更改为使用版本化引用。为了减少这种情况再次发生的可能性,指向网站上的一个样式表,该样式表将导入所需的样式表。这会将整个过程置于网站存储库的范围内,因此下次切换版本时,只需在此处进行更改,从而降低遗漏的可能性。根据与 Peter Geoghegan 和 Jonathan Katz 的(离线)讨论。https://git.postgresql.org/pg/commitdiff/d22d0fa937616a3112f69ebd6a6ed4f039162441

Álvaro Herrera 提交

Amit Kapila 提交

Peter Geoghegan 提交

  • 在已删除的 nbtree 页中使用完整的 64 位 XID。否则,我们可能会因使已删除页面无限期不可回收而“泄漏”它们。Commit 6655a729 对 GiST 索引中的已删除页面做了同样的事情。这项工作在此被用作起点。停止在 nbtree 元数据页中存储表示所有已删除但未回收页面的最旧 bpto.xact 的 XID。不再需要关心此条件/最旧 XID。它只在 _bt_vacuum_needs_cleanup() 需要考虑回绕时才有意义。btm_oldest_btpo_xact 元数据字段已被重新利用和重命名。它现在是 btm_last_cleanup_num_delpages,用于记住上次 VACUUM 操作中剩余的未回收已删除页面的数量(实际上,它的值通常是在上一次设置该字段的特定 VACUUM 操作中“新删除”的页面的确切数量)。存储 btm_last_cleanup_num_delpages 的总思路是,在 _bt_vacuum_needs_cleanup() 中使用它来“稍微”考虑未回收的已删除页面——但永远不要考虑太多。我们只需要避免永久留下过多的已删除页面处于未回收状态。我们这样做只是为了覆盖某些狭窄的情况,即没有其他因素导致 VACUUM 执行完全扫描,但索引仍在增长(因此实际上错过了回收现有已删除页面)。这些元数据更改带来了明显的用户可见的好处:我们不再仅仅因为拥有来自一个非常大的索引的 1 或 2 个已知已删除(但未回收)块就触发 VACUUM 操作期间的完全索引扫描。现在唯一重要的是随着时间的推移平衡成本和收益。修复自 commit 857f9c36 以来一直存在的问题,该提交添加了“跳过索引全扫描”机制(即 _bt_vacuum_needs_cleanup() 逻辑)。btm_last_cleanup_num_heap_tuples 的准确性意外地依赖于源值存储的*时间*。我们现在总是在 btvacuumcleanup() 中存储 btm_last_cleanup_num_heap_tuples。这可以修复问题,因为 IndexVacuumInfo.num_heap_tuples(源字段)预计会准确地指示 VACUUM 在 btvacuumcleanup() 中完成后的表状态。此提交无法轻松提取可回溯的修复程序。该问题的针对性修复将在后续提交中进行,但今天不会发生。我(pgeoghegan)选择从 vacuum_cleanup_index_scale_factor GUC/参数的文档中删除对已删除页面的任何提及,因为用户不再太关心已删除(但未回收)页面的存在。vacuum_cleanup_index_scale_factor 的文档描述无论如何似乎都很模糊,而且可能很快就需要重写。也许届时会添加一些关于页面删除的顺带提及。由于 nbtree WAL 记录现在使用完整的 XID,因此增加 XLOG_PAGE_MAGIC。作者:Peter Geoghegan pg@bowt.ie 审阅者:Masahiko Sawada <sawada.mshk@gmail.com> 讨论:https://postgr.es/m/CAH2-WznpdHvujGUwYZ8sihX=d5u-tRYhi-F4wnV2uN2zHpMUXw@mail.gmail.com https://git.postgresql.org/pg/commitdiff/e5d8a999030418a1b9e53d5f15ccaca7ed674877

  • VACUUM VERBOSE:计算“新删除”的索引页。教 VACUUM VERBOSE 报告*当前* VACUUM 操作删除的页面——这些是新删除的页面。VACUUM VERBOSE 继续报告整个索引中已删除页面的总数(那里没有变化)。前者是后者的子集。每类已删除索引页之间的区别仅在支持页面删除并且为性能原因与页面回收分离的索引 AM 中出现。这是 commit e5d8a999 的后续工作,该提交将 nbtree 中删除页面的 XID 存储为 64 位(而不是 32 位)。请注意,该提交添加的 btm_last_cleanup_num_delpages 元数据字段通常设置为 pages_newly_deleted。例外情况(它们不相等的情况)似乎都是实现(页面删除和回收)中的棘手情况。作者:Peter Geoghegan pg@bowt.ie 讨论:https://postgr.es/m/CAH2-WznpdHvujGUwYZ8sihX%3Dd5u-tRYhi-F4wnV2uN2zHpMUXw%40mail.gmail.com https://git.postgresql.org/pg/commitdiff/2376361839091b0dcdcc0b77f938b809b5f21646

David Rowley 提交

Noah Misch 推送

待处理补丁

Justin Pryzby 发送了一个补丁的另一个修订版,该补丁使 INSERT SELECT 使用 BulkInsertState 和 multi_insert,检查易失性默认值以确保不丢失对它们的任何依赖,使 COPY 根据累积的元组大小而不是行长度刷新 multi-insert 缓冲区,并检查元组大小以更准确地测量块大小,以计算何时刷新缓冲区。

Hou Zhijie 发送了一个补丁的另一个修订版,该补丁添加了一个 GUC 和一个每表选项,都命名为 enable_parallel_dml,以控制 DML 是否包括并行执行的选项。

Bharath Rupireddy 发送了一个补丁的另一个修订版,该补丁在 FDW 级别和外部服务器级别都添加了名为 keep_connections 的 GUC。

Masahiko Sawada 发送了一个补丁,用于检查是否应该进行索引 vacuum(和 heap vacuum),基于是否有 1% 的所有 heap 页具有 LP_DEAD 行指针。

Shenhao Wang 发送了一个补丁,使 --enable-coverage 在找不到 lcov 的情况下也能成功,因为实际的覆盖率测试可以在没有它的情况下运行。

Jim Mlodgenski 发送了一个解析器钩子的补丁。

Mats Kindahl 发送了一个 TableAccessMethod 的回调补丁,当表应被安排解除链接时调用,并为 heap 访问方法实现了该方法。

Justin Pryzby 发送了另外三个修订版的补丁,用于在 typinput 中出错时报告文本参数,并用二进制参数测试错误时的参数输出。

Daniel Gustafsson 发送了另外两个修订版的补丁,使 libpq 的 TLS 后端可以使用 NSS。

Jan Wieck 发送了一个补丁的另一个修订版,用于使线协议可插拔,并使用它通过 telnet 进行响应。

Justin Pryzby 发送了另一个补丁的修订版,用于修饰即将发布的文档。

Iwata Aya 和 Álvaro Herrera 交换了补丁,以改进 libpq 的跟踪能力。

Amit Kapila 发送了一个补丁,用于更新文档和注释,以匹配当前行为的已准备事务的解码。

Daniel Gustafsson 发送了另一个补丁的修订版,用于检查 pg_upgrade 中目标集群二进制文件的版本。

Mark Rofail 发送了另一个补丁修订版,用于实现外键数组。

Matthias van de Meent 发送了一个补丁的另一个修订版,用于添加 COPY 进度报告的可报告组件,包括一个新视图 pg_stat_progress_copy,向进度报告文档添加反向链接,并为此添加回归测试。

Dilip Kumar 发送了另外三个修订版的补丁,用于提供一个获取恢复暂停状态的新接口 pg_get_wal_replay_pause_state,该接口返回实际的恢复暂停状态,即如果未请求暂停则为“未暂停”,如果请求了暂停但恢复尚未暂停则为“请求暂停”,如果恢复实际上已暂停则为“已暂停”。

KaiGai Kohei 发送了一个补丁,为 contrib/cube 添加了二进制输入/输出处理程序。

Georgios Kokolatos 发送了另一个补丁的修订版,以使 dbsize 更加一致。

Mark Dilger 发送了一个补丁的另一个修订版,用于添加 pg_amcheck,一个用于在表和索引上运行 amcheck 验证的命令行界面。

John Naylor 发送了另外两个修订版的补丁,用于通过 SIMD 指令验证 utf-8。

Hayato Kuroda 发送了三个修订版的补丁,用于重构 ECPGconnect 并允许在那里进行 IPv6 连接。

Amit Langote、Greg Nancarrow 和 Amit Kapila 交换了补丁,使 INSERT (INTO ... SELECT ...) 可以使用多个工作进程执行。

Julien Rouhaud 发送了一个补丁的另一个修订版,用于向 REINDEX 添加一个新的 COLLATION 选项。

John Naylor 发送了两个修订版的补丁,允许将元组插入几乎为空的页面。

Paul Martinez 发送了另外两个修订版的补丁,用于记录 max_replication_slots 对订阅方的影响。

Ajin Cherian 和 Amit Kapila 交换了补丁,以避免在重启后重复解码已准备的事务,并添加了一个选项以在 pg_create_logical_replication_slot 中启用两阶段提交。

Peter Eisentraut 发送了另一个补丁的修订版,用于修复光标敏感性术语的使用,使其与 SQL 标准中的术语匹配,删除了敏感光标受支持的声明,并为光标添加了一个新的选项 ASENSITIVE,这是默认行为。

Benoit Lobréau 发送了一个补丁,用于更详细地记录 archive_command 如何根据发送的信号失败,以及它是否在 pg_stat_archiver 中报告。

Peter Eisentraut 发送了另一个补丁的修订版,用于为来自客户端的 SSL 连接设置 SNI,这允许感知 SNI 的代理路由连接。

Peter Smith 发送了三个修订版的补丁,用于实现两阶段事务的逻辑解码。

Amit Kapila 发送了另一个补丁的修订版,用于更新逻辑复制的文档,以包含最近添加的逻辑复制配置设置,并提及表同步工作进程现在使用复制源来跟踪进度。

Thomas Munro 发送了另一个补丁的修订版,用于将缓冲区 I/O 锁替换为条件变量。

Amit Langote 发送了另一个补丁的修订版,用于修复分区行移动的错误行为,通过确保在分区表上创建外键触发器,并使用它们在跨分区更新期间正确强制执行外键。

Thomas Munro 发送了另一个补丁的修订版,用于防止 latches 将信号发送给当前未休眠的进程,使用 SIGURG 而不是 SIGUSR1 进行 latches,使用 signalfd 进行 epoll latches,通过等待 signalfd 而不是信号处理程序和 self-pipe 来减少系统调用和其他开销,并为 kqueue latches 使用 EVFILT_SIGNAL。

Michaël Paquier 发送了一个补丁,为 reindexdb 添加了一个 --tablespace 选项,匹配 REINDEX 最近添加的功能。

Kota Miyake 发送了一个补丁,用于修复 pgbench 在同时设置 PGUSER 和 PGPORT 时报告数据库名称的错误。

Amul Sul 发送了另一个补丁的修订版,用于使用全局屏障实现 wal 禁止状态,在 START_CRIT_SECTION 之前进行 WAL 写入的错误或断言,并记录相同内容。

Justin Pryzby 发送了另一个补丁的修订版,用于使 CREATE INDEX CONCURRENTLY 可以在分区表上使用。

Jacob Champion 发送了另一个补丁的修订版,用于保存用户原始已认证身份以用于日志记录。

Daniel Gustafsson 发送了另一个补丁的修订版,通过忽略启用 SSL 压缩的选项来禁止 SSL 压缩。稍后的补丁将完全删除该选项,因为它现在已弃用。

Daniel Gustafsson 发送了一个补丁,用于移除 libpq authtype 参数中的默认值,因为它已被弃用。

Álvaro Herrera 发送了另一个补丁的修订版,用于实现 ALTER TABLE .. DETACH PARTITION CONCURRENTLY。

Dilip Kumar 发送了另外两个修订版的补丁,用于使表可以设置压缩类型。

Euler Taveira de Oliveira 发送了另一个补丁的修订版,用于通过在 PUBLICATION 的 DDL 中使用可选的 WHERE 子句来实现逻辑复制的行过滤。

Thomas Munro 发送了另一个补丁的修订版,用于引入 FeBeWaitSet 位置的符号名称,并对 walsender.c 使用 FeBeWaitSet。

Thomas Munro 发送了另一个补丁的修订版,用于使用条件变量实现 ProcSignalBarriers,允许在中断代码中使用条件变量,并使用全局屏障来修复 Windows 上的 DROP TABLESPACE,方法是强制所有后端在该平台上关闭所有文件描述符。

Andrey Borodin 发送了一个补丁,用于 FPI 使用不同的压缩方法。

Julien Rouhaud 发送了一个补丁,用于将 pg_prewarm 和 pg_stat_statements 中的显式对齐使用更改为 CACHELINEALIGN,并更新 hash_estimate_size() 中的对齐,使其估计 ShmemInitHash 将实际消耗的量(基于 CACHELINEALIGN)。

Thomas Munro 发送了一个补丁,用于移除 Linux < 2.6.27 的 latch.c 变通方法。

Peter Eisentraut 发送了另一个补丁的修订版,用于 psql,该补丁使 psql 默认显示所有查询结果。

Jeff Janes 发送了一个补丁,用于使 SCRAM 的行为与 MD5 匹配,在密码不匹配用户时报告一个 DETAIL 消息。

Joel Jacobson 发送了一个 regexp_positions() 函数的补丁。

Paul Förster 发送了一个补丁,用于在 psql 的 --help 输出中提及数据库 URI。

Justin Pryzby 发送了一个补丁,用于重构 ATExec{En,Dis}ableRowSecurity,使其风格与 ATExecForceNoForceRowSecurity 相同,并进行进一步重构。

Justin Pryzby 发送了一个实现 ALTER TABLE SET TABLE ACCESS METHOD 的补丁。