开发者开源了四个基于 Rust 的 PostgreSQL 工具,为社区生态注入新活力。tree-sitter-postgres 作为 SQL 和 PL/pgSQL 的语法解析器,其优势在于能够通过自动化流程从 PostgreSQL 的 Bison 源文件生成代码,这大大简化了与 PostgreSQL 新版本保持同步的难度。libpgfmt 是一个专注于格式化 SQL 和 PL/pgSQL 代码的 Rust 库,它内置了多种样式预设,例如 aweber、dbt、gitlab 等。基于此库构建的命令行工具 pgfmt,则方便开发者直接格式化或检查 SQL 代码。libpgdump 用于读写 PostgreSQL 转储文件(支持自定义、目录和 tar 格式),是作者另一个项目 pgdumplib 的 Rust 移植版本。
https://www.postgresql.org/about/news/tree-sitter-postgres-libpgfmt-pgfmt-and-libpgdump-3263/
pg_textsearch v1.0 正式发布
pg_textsearch v1.0 已正式发布,这是一个采用 Postgres 许可证的开源 PostgreSQL 扩展。该扩展提供了现代化的 BM25 排序算法,以实现关键词搜索功能,并具备快速索引和高性能查询能力。根据官方发布的基准测试结果,在大规模信息检索数据集上,该扩展的性能显著优于采用更严格 AGPL 许可证的 ParadeDB。这款由 Timescale 开发的扩展,旨在为 PostgreSQL 用户提供前沿的全文搜索解决方案。
https://www.postgresql.org/about/news/pg_textsearch-v10-3264/
Estuary 增强 PostgreSQL CDC 能力
Estuary 对其 PostgreSQL 连接器进行了重要更新,显著增强了变更数据捕获 (CDC) 的功能。新增的只读模式不再依赖水印表,并支持从 PostgreSQL 备用副本捕获数据,这要求 PostgreSQL 版本在 16 以上,且启用了逻辑解码和 hot_standby_feedback 设置。此外,连接器现在支持 IAM 认证(适用于 AWS、GCP 和 Azure 平台),减少了对静态数据库凭据的依赖。另一个关键更新是“按分区捕获分区表”功能,它允许将每个分区作为独立的流进行处理,为分区数据提供了更精细的控制粒度。这些改进共同提升了生产环境中 CDC 流程的安全性和运维灵活性。
https://www.postgresql.org/about/news/postgresql-cdc-evolved-read-only-mode-iam-auth-partition-support-now-in-estuary-3261/
pg_ash v1: 纯 SQL 实现的活跃会话历史工具
pg_ash v1 为 PostgreSQL 数据库引入了 Active Session History (ASH) 功能,其核心是通过 pg_cron 每秒对 pg_stat_activity 进行采样。这是一个纯 SQL/PL/pgSQL 的解决方案,无需编译 C 扩展、修改 shared_preload_libraries 或重启数据库服务,因此完美兼容 RDS、Cloud SQL 等托管 PostgreSQL 服务。工具将编码后的快照存储在分区表中,每个样本约占用 100-200 字节,每日存储量约为 30 MiB,并支持自动分区轮转。它提供了多达 32 个 SQL 函数,用于全面的等待事件分析,例如识别顶级等待事件、按查询进行等待分析、深入钻取和时间线可视化。这些函数的设计支持链式调用,便于人工操作或 AI 工具进行迭代式的根因分析。该工具兼容 PostgreSQL 14 至 18 版本。
https://www.postgresql.org/about/news/pg_ash-v1-active-session-history-for-postgresql-3242/
应对磁盘绑定数据的性能悬崖
数据库性能往往遵循一个可预测的模式:当所有数据都能放入内存时,响应速度极快;但当“工作集”(即频繁访问的数据)大小超过可用 RAM 时,性能会出现断崖式下跌。这种“性能悬崖”可能导致查询响应时间从毫秒级骤增至数百毫秒。问题的根源在于缓存淘汰机制——新数据会迫使旧数据被写入磁盘,后续查询访问这些被淘汰的数据时,就必须等待缓慢的磁盘 I/O。当分析查询扫描大量历史数据,并将近期的“热”数据挤出内存时,会引发“缓存污染”,进一步加剧问题。常见的解决方案包括垂直扩展(增加 RAM)、水平分片,或者切换到列式存储以减少数据占用空间。开发者可以通过监控 PostgreSQL 的 pg_statio_user_tables 视图中的缓存命中率来预警;如果命中率低于 95%,则可能预示着性能问题即将发生。
https://www.tigerdata.com/blog/surviving-performance-cliff-disk-bound-data
PostgreSQL Hacker 邮件讨论精选
REPACK [CONCURRENTLY] 的用法探讨
讨论聚焦于完善 REPACK CONCURRENTLY 功能的实现。Antonin Houska 提交了 v48-0006 版本,这是一个替代实现,允许每个数据库运行一个 REPACK 后端,而非之前设计的每个集群一个。Alvaro Herrera 整合了这个改动并发布了 v50,解决了几个问题:通过将 XLogGetInsertRecPtr() 替换为 XLogGetInsertEndRecPtr() 修复了 WAL 刷新请求;通过在临时索引上创建约束副本来解决排斥约束问题;并添加了默认值为 5 的 max_repack_replication_slots GUC 参数。Alvaro 还建议用 CreateInitDecodingContext() 中的一个三值参数来替换全局变量 accessSharedCatalogsInDecoding,以改进 API 设计。随后发布的 v51 修复了 Windows CI 失败问题,并包含了其他改进,如 Srinath 对 PreventInTransactionBlock 的修复和增强的槽需求错误信息。文档构建失败的问题也在之后得到了解决。
https://www.postgresql.org/message-id/90475.1775218118@localhost
pg_waldump: 支持对 tarfile 中的 WAL 进行解码
讨论源于提交 ebba64c08d9 后 pg_waldump 回归测试失败的问题,该提交增加了 tar 格式验证。核心问题在于不同的 tar 实现(GNU tar、BSD tar、OpenBSD tar)使用了不同的默认格式——有些默认使用 pax 格式(pg_waldump 无法处理),而其他则使用 ustar 格式。
Sami Imseih 报告了由于 ustar 格式中 UID/GID 限制(最大值为 2^21-1 或 2097151)导致的测试失败,因为他们系统的 UID 超出了此限制。提出的解决方案是在测试 tar 文件中添加 --owner=0 --group=0 标志,以强制使用兼容的所有权值。
Thomas Munro 开发了改进 tar 可移植性的补丁,通过在不同 tar 实现中标准化使用 --format=ustar 来解决问题,包括应对 OpenBSD 最近将默认格式改为 pax 的变更。该补丁还使用 File::Spec->devnull() 解决了 Windows 兼容性问题。
Tom Lane 指出,要正确支持 pax 格式需要实现稀疏文件处理,因为在文件页面缺失时 WAL 验证会失败。他对在没有完整稀疏文件解码能力的情况下部分支持 pax 格式持保留态度。
目前的共识是在测试中强制使用 ustar 格式并覆盖所有权设置,而长期解决方案可能包括在未来开发周期中全面支持 pax/稀疏文件。
https://www.postgresql.org/message-id/CAA5RZ0tt89MgNi4-0F4onH+-TFSsysFjMM-tBc6aXbuQv5xBXw@mail.gmail.com
PATCH: jsonpath 字符串方法扩展
Andrew Dunstan 已提交了 jsonpath 字符串方法的补丁,新增了 lower()、upper()、initcap()、l/r/btrim()、replace() 和 split_part() 等方法。提交后,Marcos Pegoraro 发现文档中 btrim() 函数的示例存在一个他认为的错误。该示例显示为 jsonb_path_query('"xyxtrimyyx"', '$.btrim("xyz")'),Marcos 认为应改为 "xyztrimxyz"。然而 Andrew 澄清原示例是正确的,它演示了 btrim() 会移除参数字符串中任意字符组成的前导和尾随序列,而不是精确匹配整个字符串。Marcos 通过查阅回归测试确认了这一理解,承认 btrim() 的工作方式与标准字符串 trim 函数相同(逐字符处理),并为此前的误解致歉。
https://www.postgresql.org/message-id/40bd5c82-639d-41cd-ad85-9cd2dffd0680@dunslane.net
如何在运行中的集群里修改数据校验和的状态
Daniel Gustafsson 提交了一个基于最新代码重新整理的补丁,用于在运行中的集群内动态改变数据校验和状态,该补丁包含了 PG_CONTROL_VERSION 版本号的提升,并已准备提交。Heikki Linnakangas 提供了详细反馈,涉及启动器退出过程中的竞态条件、变量命名不一致(worker_running vs worker_pid)、函数命名清晰度(DataChecksumsInProgress vs DataChecksumsInProgressOn),以及控制文件兼容性的枚举值分配。Daniel 逐一解决了这些问题:在 launcher_exit 中实现适当的锁机制以防止竞态条件、重命名变量以提高清晰度、修复头文件依赖关系、添加显式枚举值。经过多次 CI 运行和 CFBot 重新整理代码后,Daniel 推送了这些更改,但遇到了构建机器人失败,原因是测试没有等待启动器完全退出。随后他推送了提交 0036232ba8f 来解决测试时序问题,并继续监控构建农场以发现其他潜在问题。
https://www.postgresql.org/message-id/F2EA770C-275F-41B3-A6F8-9AB12FE12BFD@yesql.se
索引预读机制补丁更新
Peter Geoghegan 发布了索引预读 (index prefetching) 补丁的第 21 版,在 v20 版确立的设计基础上进一步推进。该补丁重新调整了表访问方法 (table AM) 和索引访问方法 (index AM) 代码之间的关系,确保 indexam.c 不再直接调用 indexbatch.c,从而提高了代码的灵活性。在 v21 中,indexbatch.c 包含约 80% 的 table AM 代码和 20% 的 index AM 代码,且 table AM 完全拥有并初始化批量环形缓冲区 (batchringbuf)。补丁从 index AM API 中移除了 2 个回调函数,但在 table AM API 中添加了 2 个类似的回调。新增了一个用于标记的 table AM 回调,并且 table AM 的 index_fetch_begin 回调现在负责设置 IndexScanDescData.xs_getnext_slot。这样的设计不再需要 4 个额外的 TableAmRoutine 回调,允许 table AM 根据扫描的具体特性提供所需数量的回调函数。
https://www.postgresql.org/message-id/CAH2-WzkiCK=wELiXPgriN4r7cJzGb3Xg48E9YHrFEyEPTkynOw@mail.gmail.com