概述:你每天写的
UPDATE users SET name='张三' WHERE id=42;,在 Postgres 里几乎从不“原地修改”任何东西——它会造出一行新数据,给旧数据贴上封条,再让清扫工事后收拾残局。2026年8月13日,后端工程头部频道 Hussein Nasser 上架白板课《you won't forget how postgres works after this》,用26分钟把这件事讲成了“看过就忘不掉”的空间地图。本文以这条视频为起点,把 Postgres 的存储哲学放回整个数据库设计谱系中对照——你会看到,同一条 UPDATE 语句,在不同数据库里走的是两条完全不同的物理路径,而这些路径的差异,正是你做技术选型时最该问的那个问题。
| 项目 | 内容 |
|---|---|
| 视频标题 | you won't forget how postgres works after this(看完这期,你就忘不掉 Postgres 的工作原理了) |
| 频道 | Hussein Nasser(@hnasr,后端工程与数据库内核方向头部技术频道) |
| 发布日期 | 2026年8月13日(据本刊2026-08-28采集记录) |
| 时长 | 26分57秒(同上) |
| 播放量 | 约9.7万(2026年8月28日 YouTube 搜索页快照,本刊采集;发布约两周,对数据库内核这类垂类内容属于高热度,截至发稿未获更新的实时数据) |
| 形式 | 白板手绘课,"Intermediate and Advanced Backend Engineering Course"系列第一部分 |
| 链接 | https://www.youtube.com/watch?v=q9jixKv4h2I |
先交代频道底色。Hussein Nasser 是本刊历次后端频道盘点中的常客:本刊2026年5月至6月的四份独立记录中,该频道订阅量级在约49万至80万之间(不同批次快照数值不一,未能核实精确值),定位高度一致——“不教你用框架,只回答框架底下的原理问题”。白板、马克笔、不念PPT,是他标志性的表达方式。这条视频标题很狂,但对数据库内核垂类而言,两周近10万播放确实是一条陡峭的曲线。
视频的叙事顺序非常克制:从磁盘上的最小单位讲起,逐层向上搭出“一行数据的住所”,最后让这个结构反过来解释你日常遇到的怪现象。按叙事顺序,它讲了四件事。
第一件事:8KB 的页(Page),是 Postgres 读写磁盘的“原子”。 你的表在磁盘上不是 Excel 式的二维表格,而是由一个个 8KB 的页面串成的集合。哪怕你只想改一行100字节的数据,Postgres 也要把这行所在的整个页面读进内存、改完再写回去。行再小,IO 的计量单位也是页。这个数字是编译期常量 BLCKSZ,默认8192字节,与文件系统的块大小对齐,不能在线修改。
第二件事:表是堆(Heap),行有物理坐标。 Postgres 的表术语就叫 heap table——数据是“堆”进去的,不保证任何顺序。每一行的真正身份证不是主键,而是 CTID:(页号, 页内偏移) 的物理坐标。这就是为什么没有索引的查询只能从第0页开始一页页翻,为什么 ORDER BY 永远需要一个排序步骤。
第三件事:行头里的 xmin/xmax,是整个 MVCC 机关的钥匙。 这是全片含金量最高的部分。每一行数据前面挂着一个用户不可见的行头,藏着两个事务ID:xmin(创建此版本的事务)和 xmax(作废此版本的事务)。于是 Postgres 的 UPDATE 从不原地改数据——它写入一个新版本的行,再把旧版本的 xmax 打上标记;DELETE 也只是打标记,不立刻释放空间。读写互不阻塞的高并发能力,是用“旧版本不会自动消失”换来的,清扫工作交给 VACUUM。
第四件事:让结构解释现象,而不是背结论。 视频的后半段把前三件事串成推理链:长事务为什么是数据库公敌?因为 VACUUM 不能清理“仍可能被某个事务看见”的死版本,一个三天不提交的事务等于让全库垃圾堆三天。COUNT(*) 为什么慢?因为“这行存不存在”取决于每个事务各自的快照判断,不存在一个全局精确的计数器。删了数据为什么磁盘不变小?因为删除只是封条,文件不收缩。三个“玄学”,全部变成“显然如此”。
需要说明:以上第四部分的“结构解释现象”串联,以及下文的谱系对照,是本文基于视频主线做的延伸映射;视频本体聚焦在页面、堆、元组与 MVCC 的白板推导上。
视频最大的价值,是让你看见 Postgres 的内部结构;但如果你只看见结构本身,容易把它当成数据库的“物理规律”。它其实是一组可以追溯源头、也可以另作他选的工程决策。
POSTGRES 的出身。 Postgres 的前身是 Michael Stonebraker 在伯克利领导的 POSTGRES 项目(1980年代中期启动),名字本身就是 "Post-Ingres"——而 Ingres 是 Stonebraker 在1970年代更早的关系数据库实验。POSTGRES 的原始使命之一,就是支持“对同一数据的多个版本”进行管理:版本化不是后来打的补丁,而是这个系统与生俱来的基因。Stonebraker 因包括 POSTGRES/Ingres 在内的贡献获得2014年图灵奖。也就是说,你在视频里看到的 xmin/xmax,是快五十年的学术遗产在每一行数据上的活化石。
MVCC 的思想源头。 多版本并发控制(MVCC)作为并发理论,通常追溯到 David P. Reed 1978年的 MIT 博士论文;把多版本做成商用产品化实现的先驱之一是 Jim Starkey 主导的 InterBase,Oracle 也在同期以回滚段实现了自己的“读一致性”。各家叫法不同——Oracle 叫一致性读,MySQL/InnoDB 叫快照读,Postgres 直接把版本号写进行头——但共享同一个洞见:与其让读写互相排队,不如让每个读者看自己那个时刻的快照。
对照系:InnoDB 走了另一条路。 理解 Postgres 的堆表哲学,最快的办法是看它的头号对手怎么反着做。MySQL 的 InnoDB 把表本身组织成聚簇索引(clustered index):数据行就存放在主键的 B+ 树叶子里,表即主键索引,二级索引的“指针”存的是主键值。而 Postgres 的表永远是堆,所有索引——包括主键索引——都是二级的,“指针”指向行的物理 CTID。这个分岔推演出一连串后果:Postgres 上 UPDATE 一行,所有指向它的索引都可能要跟着改(除非命中的是 HOT 更新这类优化路径),这是它更新重的根源;InnoDB 上更新可以原地改,但旧版本要塞进 undo log,靠 purge 线程事后回收,长事务同样会撑爆历史表——只是垃圾堆在了另一个房间。Postgres 的垃圾堆在表里(表膨胀),InnoDB 的垃圾堆在回滚段里(历史表变长)。两种命运,同一个人性:没有哪个数据库能凭空抹掉“旧版本”这件事。 本节的引擎对比依据 PostgreSQL 与 MySQL 官方文档(见文末参考来源)。
把这些放回视频,你会对 Hussein 的白板多一层敬意:他画的不是“数据库本来就该长这样”,而是“Postgres 这次1978年思想实验的胜利成果长这样”。胜利成果也有代价,代价也有名字。
可信的部分:物理机制的描述与官方文档一致。 8KB 页、CTID、行头 t_xmin/t_xmax、死元组、VACUUM 的角色,这些都能在 PostgreSQL 官方文档的物理存储与并发控制章节中得到印证,属于教科书级事实。视频把文档画成空间地图的转译是准确的。
第一处简化:页面里不止行头。 真实的页除了元组,还有页头、行指针(line pointer)、空闲空间和特殊空间;VACUUM 真正的工作清单里还有一件更惊悚的事——冻结事务ID、防止 txid 回绕(wraparound),这可是能让库拒绝写入的级别故障,视频完全没有触及。白板课的“清晰”是用刻意省略换来的,把它当入门地图极好,当运维手册会出人命。
第二处简化:“UPDATE=INSERT+封条”只是主路径。 索引未涉及被更新列、页内还有空间时,Postgres 走 HOT(heap-only tuple)优化,新版本留在原页内、索引无需改动。视频没有区分主路径与优化路径,初学者容易高估每次更新的索引代价。
第三处要打折的:“近10万播放”的热度口径。 9.7万在数据库内核垂类是优秀成绩,但与本文开头提到的百万级科普爆款不是一个量级,且数据为2026年8月28日的单一快照(本刊采集),既非实时,也没有第二来源交叉。本文如实标注,读者引用时请注意口径。
第四处局限:白板课没有练习。 全片推导流畅,但你“看懂了”和“你能在 pg_stat 里认出膨胀”之间隔着一条实践的沟。视频提供了心智模型,没有提供任何可操作的检查动作——这正是本文下一节要补的。
一、给生产库做一次“膨胀体检”。 视频给了你结构,官方统计视图给你仪表盘。挑一个低峰期跑:SELECT relname, n_live_tup, n_dead_tup, last_autovacuum FROM pg_stat_user_tables ORDER BY n_dead_tup DESC LIMIT 10; 死元组接近甚至超过活元组、且 last_autovacuum 是很久以前,就说明这个表的清扫工已经追不上了——那是你亲手用高频 UPDATE 造出来的“堆”。
二、把“事务要短”从口号变成制度。 两种 MVCC 命运指向同一条纪律:长事务是所有多版本数据库的公敌,无论它的垃圾堆在表里还是 undo 里。最低成本的保险是给 idle_in_transaction_session_timeout 设上限,并让代码评审多问一句“这个事务里有没有外部调用”。
三、选型时先问一句话:“你的数据库把这一行存在哪?” 聚簇还是堆,不是宗教之争,而是你的查询画像之争:主键范围扫描密集的负载天然亲近 InnoDB 式聚簇;索引多、更新密的负载要算清 Postgres 的索引重写账。看懂视频里那张8KB地图,你从此可以在架构评审桌上问出这一个问题——这就够了。
flowchart TD
A[一条 UPDATE 语句] --> B[Postgres 路径:堆表哲学]
A --> C[InnoDB 路径:聚簇哲学]
B --> B1[写入新版本 Tuple]
B1 --> B2[旧版本 xmax 打封标]
B2 --> B3[相关索引可能需指向新 CTID]
B3 --> B4[死元组滞留表中]
B4 --> B5[autovacuum 事后回收]
B5 --> B6[回收不及时 → 表膨胀]
C --> C1[主键 B+ 树内原地修改]
C1 --> C2[旧版本写入 undo log]
C2 --> C3[purge 线程事后回收]
C3 --> C4[长事务阻塞 purge → 历史表变长]
B6 --> D[共同教训:MVCC 的代价不是消灭旧版本<br/>而是决定旧版本堆在哪个房间]
C4 --> D
D --> E[选型第一问:你的数据库把行存在哪?]
本文由「51学通信」技术团队出品。51学通信由通信行业18年老兵爱卫生(微信ID: gprshome201101)维护,聚焦5G/6G核心网、3GPP标准解读、通信前沿技术深度分析。 出版作品有《5G核心网原理与实践》《IMS原理与实践》等4本通信专业书籍。知识星球「51学通信」提供深度技术答疑和行业洞察。
[!tip] 51学通信知识星球 星主:爱卫生(微信:gprshome201101)——公众号「51学通信」创办者,19 年通信行业运维与讲师经验,著有《GPRS网络信令实例详解》《EPC原理与实践》《5G核心网原理与实践》三本纸质书(各大电商平台有售)。 星球定位:深耕 5G 核心网、IMS、NFV/AI、云原生等 ICT 领域,主打运维岗位与信令分析。 当前规模:5200 篇主题 / 990 个回答,198 元/年。 加入福利:加入星球后请加爱卫生微信,拉您进知识星球年度陪伴与答疑群——不限量回复您的各种问题,另有群内分享。 AI 加持:51学通信知识星球已作为 skill 接入 WorkBuddy,使用 deepseek-4-flash 在海量星球帖子中精准找贴、找视频、找 FAQ 和案例,做总结、找文档和 PPT 等场景全覆盖。
