冻结过程
冻结过程包含两种:惰性模式和迫切模式,冻结过程通常是以惰性的模式运行,但是当满足条件,也会以迫切模式运行。在惰性模式下,冻结过程仅使用目标表对应的VM扫描死元组的页面。迫切模式相反,它会扫描所有的页面,无论是否包含死元组,都会更新与冻结过程相关的系统视图,并在可能的情况下删除CLOG。
惰性模式
开始冻结处理时,pg计算freezelimit_txid,并冻结t_xmin小于freezelimit_txid的元组。公式:
freezeLimit_txid=(OldestXmin−vacuum_freeze_min_age) #vacuum_freeze_min_age是一个配置参数,默认值为:50,000,000
OldestXmin是当前正在运行最早的事务标识。比如正在运行vacumm,有三个事务txid分别为:100 、101、102,那么OldestXmin=100。如果不存在事务,OldestXmin就是当前vacuum命令的事务标识。举例说明惰性模式:
假如OldestXmin为50,002,500
第0页面:
三条元组被冻结,因为所有元组t_ximin都小于2500,此外,以为tuple1为死元组,所以在该清理过程中被删除。
第1页面:
通过引用VM,发现该页面所有元组都可见,清理过程跳过了对该页面的清理。
第2页面:
tuple7和tuple8被冻结,且tuple7被移除。。
如上面例子所展示,因为惰性模式可能跳过页面,它可能无法冻结所需要冻结的元组。
迫切模式
迫切模式弥补了惰性模式的问题,会扫描所有页面,检查表中所有元组,更新相关的系统视图,并在可能时删除不必要的CLOG与页面。
当满足以下条件,会执行迫切模式:
pg_database.datfrozenxid<(OldestXmin−vacuum_freeze_table_age),其中datfrozenxid是系统视图pg_database中的列,并保存每个数据中最老的已经冻结的事务标识。
vacuum_freeze_table_age是系统配置参数,默认值为:150,000,000。假设pg_database.datfrozenxid=1821
- OldestXmin−vacuum_freeze_table_age=2000 满足迫切模式:pg_database.datfrozenxid<(OldestXmin−vacuum_freeze_table_age),即1821<2000,小于2000需要冻结
- freezeLimit_txid=(OldestXmin−vacuum_freeze_min_age)=100,002,000,对于惰性模式满足这个条件的也需要冻结
第0页:
即使所有元组都被冻结,也会检查tuple2和tuple3(9.5或者更低版本)
第1页:
冻结所有页面,因为t_xmin小于freeelimint_txid。在惰性模式下,会跳过此页面,因为所有tuple都可见
第2页:
除了tuple11都冻结。
冻结一张表后,该表的pg_class.relfrozenxid将被更新。在完成清理过程之前,必要时会更新pg_database.datfrozenxid,即database下所有table都被更新后,会更新pg_databse.datfrozenxid.
改进迫切模式的冻结过程
9.5以及以下版本的迫切模式,导致table的所有页面都要被扫描,效率很低。9,5以后,使用VM存储哪些页面都被冻结,则可以跳过该页面,提高效率。