PostgreSQL的MVCC实现机制是采用数据块中生成多个副本的方式的,这种机制被很多DBA和架构师认为是PostgreSQL数据库在大型高负载系统中的一个巨大的缺陷。实际上不只是PostgreSQL采用了多副本行元来实现MVCC,目前比较热门的基于LSM-Tree存储引擎的数据库系统(比如阿里的Oceanbase,PingCAP的TiDB)也采用了这种方式。LSM-Tree需要通过Compare And Merge这种开销更大的方式来进行老元组的合并重组,而PostgreSQL使用Vacuum机制来进行数据整理。
可能很多朋友都认为Vacuum的开销很大,对数据库表的性能影响也很大,甚至在出现过Vacuum影响业务系统之后,关闭了AutoVacuum。在PostgreSQL 9之前,Vacuum的算法确实对高负载数据库的影响很大,甚至那时候笔者认为PostgreSQL的MVCC的缺陷会影响PostgreSQL在企业级应用中的使用。不过随着这些年PostgreSQL数据库的快速发展,每个版本对Vacuum的算法都有了极大的改善,在目前硬件性能极大提升与PostgreSQL Vacuum的算法的优化双重作用下,目前Vacuum对高负载数据库的影响也越来越低了。
可能还有一些朋友可以举出一些反例,说我们的数据库因为Vacuum而导致数据库性能出现严重问题了。确实可能会出现这样的反例,不过如果仔细分析一下,通过对PostgreSQL数据库的性能优化,这些反例中遇到的问题大多数都是可以解决的。
前阵子我在网上看到过一个某互联网汽车租赁公司的案例,他们的PostgreSQL数据库的AutoVacuum出现了严重的性能问题,租车订单表每天要消耗几百万个xid,而每天的autovacuum只能回收其中70%的xid,这意味着一个十分严重的问题,xid wraps的问题。当系统运行一段时间之后,就必须进行停库维护,通过vacuum来完成xid的完全回收,从而防止未回收xid达到20亿这个可能导致数据库停库的问题出现。当时客户已经在讨论是不是要通过更换数据库来彻底解决这个问题了,不过后来的一次数据库优化让这个系统摆脱了xid wraps困境。
整个优化工作也十分简单。仅仅是一些Postgres