子事务是 PostgreSQL 性能杀手吗?
本期播客
子事务是 PostgreSQL 性能杀手吗?
近期看到一篇文章, 讨论 PostgreSQL 子事务, 它到底是不是性能杀手?
https://shaneborden.com/2026/02/10/do-postgresql-sub-transactions-hurt-performance/
在 PostgreSQL 的性能调优指南中,“禁用子事务”几乎是一条被写进教科书的铁律。但很多开发者不解:我只是写了一个简单的 EXCEPTION 块,或者在代码里用了几个 SAVEPOINT,怎么就成了拖垮整库的“杀手”?
今天,我们一起来撕开这个温情脉脉的语法糖包装,看看子事务是如何通过底层的 SLRU 缓存惩罚机制,一步步将你的数据库推向崩溃边缘。
一、 痛点:被误解的“安全感”
开发者最爱用的代码结构之一就是:
BEGIN
-- 执行一些业务逻辑
EXCEPTIONWHEN OTHERS THEN
-- 报错了也不要紧,继续下一条
END;
现状: 这种写法在逻辑上非常健壮,但在 PostgreSQL 内部,EXCEPTION 块的本质就是开启了一个 子事务(Subtransaction) 。
后果: 每进入一次 EXCEPTION 块,系统就要消耗一个事务 ID(XID),并生成一个“保存点(Savepoint)”。
本质: 这种“安全感”是有代价的——它不仅在浪费有限的 XID 资源,更是在挑战内核共享内存的极限。
二、 技术剖析:从“内存闪电”到“磁盘泥潭”
PostgreSQL 处理子事务的逻辑遵循一个核心的第一性原理:局部性优化。
1. 64 位限制:性能的分水岭
PG 内核为每个进程提供了一个固定大小的数组(PGPROC),最多只能容纳 64 个 活跃的子事务 ID。
安全区(Depth < 64): 子事务 ID 存储在快速的局部内存中,性能开销微乎其微。 溢出区(Depth > 64): 一旦嵌套深度超过 64,或者单事务内累积了大量子事务,PG 必须将这些 ID 溢写到慢速的 SLRU 缓存(pg_subtrans) 中。
2. 灾难性的非线性退化
当进入 SLRU 阶段,情况会急剧恶化。
锁争用: 所有的连接在检查事务状态时,都可能去争抢同一个 SLRU 缓冲池的锁(ControlLock)。 数据支撑: 实验证明,在单用户模式下,溢出 64 层的子事务开销可能只增加 1% 左右;但一旦并发压力上升(如 10 个以上用户),由于锁竞争,执行时间会发生 50x-100x 的爆炸式增长。
三、 权威实测:WAL 与 XID 的“大胃王”
通过对 5000 行记录插入的基线测试,数据揭示了令人震惊的事实:
| 标准循环(Base) | ||||
| 单层 Exception | ||||
| 溢出 128 层 |
关键结论:
WAL 暴增: 即使数据量一样,子事务为了记录“保存点”元数据,生成的日志量是普通插入的 10 万倍。 XID 枯竭: 仅仅插入 5000 条数据就烧掉了 64 万个 XID。这会直接导致 Autovacuum Freeze 提前到来,甚至最严重的情况引发全库只读锁死。
四、 逻辑的崩塌:如果业务必须用呢?
前提假设: 我们假设子事务是处理“批量插入并忽略错误”的唯一手段。
条件崩塌: 如果你是在处理唯一键冲突,PG 提供了更优雅、更原生的方案:INSERT ... ON CONFLICT DO NOTHING。
引申观点: 只有在处理无法预知的非约束性错误时,EXCEPTION 才是必须的。如果逻辑崩塌,我们应该采取以下防御性编程策略:
数据预校验: 在应用层或临时表中先过滤掉脏数据,而不是丢给数据库去捕获异常。 批量而非逐条: 严禁在循环(LOOP)内部嵌套 EXCEPTION块。监控真理: 不要只看 CPU,去查 pg_stat_slru。如果blks_read激增,说明你的子事务已经打穿了内存。
说到这, 我在这个 Skill 中包含了该监控: https://github.com/digoal/postgres_skill
结语
子事务不是洪水猛兽,但在 PostgreSQL 中,它确实是一个带刺的工具。
它在小规模、低深度的场景下优雅好用,但一旦并发升高、深度过载,它就会触发全局锁竞争,让你的数据库瞬间陷入“僵死”状态。
那么问题来了:你现在的 PL/pgSQL 存储过程里,是不是还写着那个看似万能、实则致命的 WHEN OTHERS THEN NULL?
最后附一则济南的线下峰会消息:
PostgreSQL & IvorySQL 2026 年度峰会将于4月份在济南召开,这是目前国内规模最大的PG峰会.
我是新特性分论坛出品人,欢迎报名参与分享,主委会可解决分享嘉宾住宿和路费。
报名地址: https://jsj.top/f/uebqBc
议题方向:
PostgreSQL 新功能 PostgreSQL 内核机制与性能优化 PostgreSQL 扩展程序 AI + PostgreSQL 技术实践 云原生PostgreSQL或IvorySQL PostgreSQL 用户实践 IvorySQL 兼容性与生态实践 基准测试与性能调优 高可用性技术 …… 任何与PostgreSQL或IvorySQL相关的内容