Folia
← 返回头版

PostgreSQL的MVCC设计与行业通病:多版本并发控制无完美方案

一篇对多个数据库系统的深度分析指出,PostgreSQL的多版本并发控制(MVCC)存在的问题并非其独有,而是反映了整个行业在版本管理设计上面临的普遍困境1。该分析对比了PostgreSQL、Oracle/InnoDB、SQL Server、MongoDB和LSM引擎等多个系统,梳理出MVCC的四个核心设计权衡——版本存储位置、版本链方向、索引指向方式、清理机制——指出每种技术路线都存在其失败模式,不存在完美解决方案1。

PostgreSQL采用的设计方案具有鲜明特点:版本数据存储在表内、版本链从旧指向新、索引直接指向物理位置、由后台进程执行清理1。这套方案的代价是写放大严重——单行默认产生7.1条预写日志(WAL)记录,即便通过HOT更新优化也仅能降至3.0条1。更为棘手的是,一个未提交的事务可阻止整个数据库的垃圾回收,这被称为xmin horizon问题1。此外,PostgreSQL采用32位事务ID需要定期冻结元组以防溢出,这是其独有的维护负担1。Uber在2016年对PostgreSQL的测量正是基于这些写放大问题,最终促使该公司转向MySQL1。

相比之下,其他系统采取了不同的折衷方案,各自面临独特的困境1。InnoDB和Oracle使用undo日志设计,使回滚成本等同于事务成本1。Oracle、InnoDB和MongoDB中都普遍存在"快照过旧"类错误(如ORA-01555)1。SQL Server将版本存储在tempdb中,长事务会导致整个实例故障1。MongoDB则将版本存储在内存,缓存压力下会直接回滚事务,其失败模式表现为延迟而非错误1。CockroachDB和YugabyteDB采用LSM树架构,垃圾回收窗口历史上的默认设置为25小时1。

业界也在尝试改进方案1。etcd采用类似PostgreSQL的设计,同样面临bloat和快照过旧问题1。PostgreSQL社区在2018年启动了zheap项目,试图为该系统添加undo引擎,但多年后仍未被主分支采纳1。另一个方向是OrioleDB,它结合了undo式版本控制与索引组织表,由Alexander Korotkov在Supabase维护1。


评论