#postgresql#
颠覆认知!PG没有Undo Log,为啥回滚比MySQL快100倍?
核心关键词:堆表MVCC、O(1)声明式回滚、xmin/xmax/t_ctid、pg_clog、无Undo Log架构、Auto Vacuum、表膨胀、XID Freeze、JEEP项目、可见性判断
同样是数据库回滚,差距到底有多大?
MySQL回滚百万条数据,动辄卡死、Undo日志爆满、数据库卡顿崩溃。
PostgreSQL回滚百万条数据,1秒搞定,和回滚1条数据耗时一模一样。
很多人疑惑:MySQL靠Undo Log实现回滚和MVCC,是行业通用逻辑。可PG从头到尾根本没有Undo Log,翻遍源码、Data数据目录,找不到半个相关文件。
它到底靠什么实现事务回滚、多版本控制?
今天一次性讲透MySQL与PG的底层架构差异,看懂数据库最核心的取舍之道,读懂为什么没有完美的数据库,只有合适的取舍!

用一个仓库货位的通俗比喻,彻底分清两者的核心区别,没有任何晦涩术语。
MySQL的更新,是直接覆盖旧数据:
1、修改数据前,先把旧数据抄写进「Undo Log抽屉」存起来;
2、直接擦掉原数据,写入新数据;
3、如果需要回滚,再从抽屉里拿出旧数据,重新写回去。
致命缺点:修改的数据越多,抽屉里的日志越多,回滚需要回放的数据量就越大。
百万级大事务,直接导致Undo Log爆满,数据库IO飙升、卡顿甚至宕机。
PG完全反其道而行之,永远不删、不改旧数据:
1、更新数据时,不碰旧数据,直接在旁边新增一行新数据;
2、给旧数据打一个「已失效」标记,物理数据纹丝不动;
3、事务回滚时,不修改任何数据,只贴一张「本事务作废」的公告。
核心优势炸裂:不管你修改1行、100万行、千万行数据,回滚只需要改一个状态。
恒定O(1)速度,事务再大,回滚都是秒级完成!
PG之所以能抛弃Undo Log,核心是每一行数据,都自带三大隐藏身份证字段,完美替代Undo的所有能力,这是PG独有的内核设计。
PG所有增删改操作,不会擦除半个字节的物理数据,全程只修改这三个字段的数值,迭代出完整的数据版本链。
很多人以为更新是覆盖数据,PG完全不是:
1、给旧数据的xmax打上当前事务ID,标记旧数据失效;
2、在数据页空闲位置,全新写入新版本数据;
3、用t_ctid指针关联新旧数据,形成完整版本链路。
全程无数据覆盖、无日志回放,从根源解决大事务卡顿问题。
PG有一个核心系统表 pg_clog,专门记录所有事务状态。
最离谱的是:每一个事务,只占用2bit存储空间。
仅用2bit,就能标记四种状态:进行中、已提交、已回滚、子事务。
PG回滚的全过程,简单到离谱:
不需要读数据、不需要写旧值、不需要回放日志。
只需要把pg_clog里的2bit状态,从「进行中」改成「已回滚」即可。
所谓回滚,只是声明事务作废,不是还原数据!
事务回滚后,旧数据还在、新数据也还在,为什么业务查不到?
因为PG把所有数据过滤逻辑,交给了可见性判断函数:
1、创建校验:事务未提交/已回滚,数据直接判定不存在;
2、失效校验:被回滚事务修改的数据,默认判定为有效旧数据。
所有回滚产生的「幽灵数据」,会被系统自动屏蔽,业务完全无感知。

没有最好的数据库,只有最适合的业务!两者是完全反向的设计思路:
设计逻辑:原地更新 + Undo Log存旧数据
优点:数据实时清理,数据表整洁无膨胀,运维简单、门槛低
代价:回滚耗时和数据量成正比,大事务必卡顿、必压垮Undo日志,依赖Purge线程持续清理
设计逻辑:追加新数据 + 状态标记失效,零Undo Log
优点:写性能拉满,O(1)恒定回滚速度,超大事务零卡顿
代价:失效数据持续堆积,表膨胀、索引膨胀严重,运维难度拉满
PG把写操作的性能压力,全部转移到了后期垃圾回收和运维上,也是所有PG DBA的痛点:
很多人不知道,2018年PG社区EDB团队,启动过一个JEEP项目。
核心目标:给PG加入Undo Log,对标MySQL架构,彻底解决表膨胀问题。
而且!这个项目技术上完全跑通了,功能全部实现。
但社区最终拒绝合并进主线,原因太真实:
1、引入Undo属于底层架构重构,连锁问题太多,改造成本天价;
2、二十年生态适配完成,Vacuum、并行清理、HOT更新已适配无Undo架构;
3、小迭代优化,远比推倒重来更稳定、更适配业务。
顶级工程师的智慧:接受架构短板,用生态弥补,拒绝激进重构。
日常运维PG,盯住这5个指标,就能规避90%的性能问题:
这是新手最疑惑的问题:没有Undo回放,宕机重启数据不乱吗?
答案:完全不乱,靠声明式一致性机制实现:
1、宕机前未提交的事务,数据虽然写入磁盘,但事务状态为「进行中」;
2、重启后系统自动将所有未完成事务标记为「已回滚」;
3、可见性函数自动屏蔽所有未提交数据,垃圾数据交由Vacuum后台慢慢清理。
全程无需数据回写,轻量化、零性能损耗。

1、核心本质差异:两种完全不同的回滚设计理念:MySQL InnoDB 采用命令式回滚,依赖Undo Log记录数据旧版本,回滚时必须物理回放、还原原始数据,事务数据量越大,回滚耗时越长,大事务极易引发数据库卡顿、IO飙升;而 PostgreSQL 采用独创的声明式回滚,无需修改、还原任何物理数据,仅通过修改pg_clog事务状态标识作废事务,真正实现 O(1) 恒定回滚速度,百万级大事务和单行事务回滚耗时完全一致。
2、架构取舍逻辑:性能与运维的双向博弈:PostgreSQL 将所有性能压力前置到写入阶段,舍弃传统Undo Log架构,以表膨胀、索引膨胀、Vacuum调参、XID老化等高运维成本为代价,换来了极致的写入性能、无锁并发能力和超大事务稳定运行的优势;MySQL 则选择牺牲大事务性能,依托Undo+Purge线程实时清理旧数据,保证数据表结构整洁、运维门槛极低,更适配中小事务、稳定运维的常规业务场景。
3、底层架构核心:PG无Undo的核心支撑体系:PG 彻底摒弃MySQL依赖的Undo Log回滚段体系,依靠xmin/xmax/t_ctid三元组元组头实现数据版本管理,搭配pg_clog两比特事务状态记录表、可见性判断函数,构建出独有的堆表MVCC机制,所有增删改操作仅修改字段标记,不原地覆盖、不删除物理数据,这也是其极速回滚、高并发写入的核心底层支撑。
4、行业核心真理:数据库无银弹,取舍决定场景适配:没有万能的数据库架构,所有性能优势都伴随对应的代价。PG 赢在写入并发、大事务容错、回滚效率,输在垃圾回收繁琐、运维难度高、存在膨胀风险;MySQL 赢在运维简单、数据整洁、生态成熟,输在大事务容错差、回滚效率弱。二者不存在优劣之分,业务场景、运维能力、数据体量,才是选择数据库架构的核心标准。
5、落地实战启示:PG 看似“无代价”的秒级回滚,实则把所有压力转移至后期Vacuum垃圾回收与日常运维,这也是官方即便启动JEEP项目、攻克Undo Log适配技术难题,仍拒绝合并主线的核心原因——成熟的生态迭代,远比激进的架构重构更适配生产稳定需求。日常运维中,把控长事务、监控表膨胀、定期XID老化,是稳住PG性能的核心关键。
更新时间:2026-06-09
本站资料均由网友自行发布提供,仅用于学习交流。如有版权问题,请与我联系,QQ:4156828
© CopyRight All Rights Reserved.
Powered By 61893.com 闽ICP备11008920号
闽公网安备35020302035593号