PG 19了,32位XID狗皮膏药能不能撕掉?
本期播客
PostgreSQL 19 preview - 32位XID狗皮膏药到底能不能撕掉?
哎呀,终于等到这个话题了!一看到这个补丁,我的心里就响起了那首熟悉的歌: “狗皮膏药,贴了又揭,揭了又贴,它就是不肯走……”
那块 32 位 XID 的“祖传狗皮膏药”
XID 的“祖传秘方”: 很久很久以前,当我们还在用 32 位操作系统、硬盘以 GB 计费的年代,32 位的事务 ID(XID)被认为是“足够用”的。 现实的巴掌: 谁能想到现代 OLTP 系统如此疯狂?随着 SSD、高并发和云数据库的普及,每天跑几十亿甚至上百亿个短事务成了常态。这 个 XID,在高负载下可能几天甚至不到一天就用完了! 狗皮膏药的副作用: 当 XID 快用完时,PostgreSQL 的守护进程 autovacuum就得紧急出动,像一个拿着鞭子的老管家,拼命地对所有表进行 “防回卷 VACUUM (anti-wraparound VACUUM)” 。这操作,轻则引起 IO 抖动,重则直接把 CPU 和磁盘榨干,让整个数据库进入 “僵尸模式” 。
下面这个PG 19的补丁,本质上是给 XID 的“穷亲戚”MultiXact 的成员偏移量续上了 64 位的命!
虽然主要的 XID 依然是 32 位(是的,那块最疼的狗皮膏药还没彻底撕掉,它需要更深层的架构变动),但通过把 MultiXactOffset 升级到 64 位,我们解决了另一个潜在的、且可能比 XID 本身更快触发的危机。这就像是:
“主 XID 的命只剩几天了,但至少我们确保,在它挂掉之前,它不会因为 MultiXact 的‘成员’太多而提前被勒死!”
这次升级,算是 PG 社区在迈向完全 64 位事务 ID 道路上的又一块重要基石,它让那些高并发、多锁操作的场景能活得更长久、更安稳。我们一边鼓掌,一边流下时代的眼泪,期待 XID 本尊彻底升级到 64 位的那一天!
其实这个补丁没什么卵用, 要耗尽肯定也是主xid先耗尽, PG社区动作还是太慢了, 步子就不能大一点吗?
补丁解读:给 XID 的“穷亲戚”续命!
https://github.com/postgres/postgres/commit/bd8d9c9bdfa0c2168bb37edca6fa88168cacbbaa
这个补丁(Commit bd8d9c9bdfa0c2168bb37edca6fa88168cacbbaa)的标题非常直接: "Widen MultiXactOffset to 64 bits" 。
简单来说,它干了一件大事:把 PostgreSQL 多事务 ID(MultiXact) 的 成员偏移量(MultiXactOffset) 从 32 位拓宽到了 64 位。
解决的问题:MultiXact 的“成员”不够用了!
MultiXact 是 PostgreSQL 用于行锁和多版本控制(MVCC)的巧妙机制。当多于一个事务需要锁定或影响同一行时,它不会为每个事务分配一个独立的 XID,而是分配一个 MultiXact ID,这个 ID 指向一个列表,列表中记录了所有相关的成员事务(Member XIDs)。
这个列表存储在一个被称为 pg_multixact/members 的 SLRU 文件中,而 MultiXactOffset 32 位限制的就是这个成员列表的总大小(或说总条目数) 。
划重点:
旧问题: 32 位的 MultiXactOffset限制了 MultiXact 成员的总数在 (大约 40 亿)左右。在高并发、长时间运行的系统上,尤其是有大量行锁操作的场景,这个成员数增长速度可能比 XID 还要快得多!一旦成员偏移量达到极限,PostgreSQL 就会被迫启动紧急防回卷清理(emergency anti-wraparound freezing) ,以释放空间。这个过程会消耗大量资源,可能导致系统性能急剧下降。 新方案: 升级到 64 位的 MultiXactOffset,理论上将成员总数限制推到了 。这个数字大到什么程度?够我们用上几千年,基本上消除了这个维度上的回卷(wraparound) 问题!
代码改动:
数据类型更改: 在 multixact.h中,将MultiXactOffset的定义从 32 位整数(uint32或类似)改为 64 位整数(uint64)。清理逻辑简化: 由于不再需要担心偏移量的回卷,代码中那些为了处理 32 位限制而设计的 “复杂角点情况” 和 “紧急防回卷” 逻辑可以被移除或大幅简化。 兼容性处理: 增加了 pg_upgrade的逻辑,用于将旧版本集群的pg_multixact文件(offsets部分)重写成新的 64 位格式,确保平滑升级。这还顺便移除了以前为了兼容旧版 bug 而设置的一些“补丁式”代码。