关系型数据库Heap Table / MVCC
堆表与 MVCC 是什么?
更新等于插入新版本,旧版本留在表里等 VACUUM 清
类比:改合同不涂改原件,而是新打一份,旧的那份先留着
和 MySQL 的根本差别
MySQL(InnoDB)是聚簇索引:数据按主键顺序存在 B+ 树里,更新时尽量原地改,旧值放 undo log。PG 是堆表:数据无序堆在页里,更新时直接写一条新记录,旧记录留在原地标为死元组。
所以 PG 没有 undo 表空间,但需要 VACUUM;MySQL 不需要 VACUUM,但需要管 undo 和 purge。
快照与可见性
每行有 xmin(创建事务)和 xmax(删除事务)。事务开始时拿一个快照,判断“这行对我可见吗”就是比较这两个值和快照范围。这带来一个好处:读写互不阻塞,读永远不会被写卡住。
代价
更新频繁的表会迅速膨胀,索引也要跟着更新(索引项指向新版本),所以 PG 的写放大比 MySQL 明显。大批量更新后建议做一次 VACUUM,或者用分区表 + 分区替换的方式规避。