简介
PostgreSQL有一个可选但是被推荐的特性autovacuum(从8.1版本加入),它的目的是自动执行VACUUM和ANALYZE 命令,回收被表示为删除状态记录的空间。对表元组的UPDATE或DELETE操作并未立即删除旧版本的数据,表中的旧元组只是被标识为删除状态,并未立即释放空间。这种处理对于多版本并发控制(MVCC)是必要的,如果一个元组的版本仍有可能被其它事务看到,那么久不能删除元组的该版本。当事务提交后,过期元组版本将对事务不再有效,因而其占据的空间必须回收以供其他新元组使用,以避免磁盘空间被消耗殆尽。

VACUUM作用
1.恢复或重用被已更新或已删除行所占用的磁盘空间。
2.更新被PostgreSQL查询规划器使用的数据统计信息。
3.更新可见性映射,可以加速索引的扫描。
4.保护老旧数据不会由于事务ID回卷或多事务ID回卷而丢失。
参数
这些设置控制autovacuum特性的行为。主要参数如下:
autovacuum (boolean)
控制服务器是否运行自动清理启动器后台进程。默认为开启, 不过要自动清理正常工作还需要启用track_counts。
autovacuum_max_workers (integer)
设置系统自动清理工作进程的最大数量。默认值为3。该参数只能在服务器启动时设置。
autovacuum_naptime (integer)
设置两次系统自动清理操作之间的间隔时间。
autovacuum_vacuum_threshold (integer)和autovacuum_analyze_threshold (integer)
设置当表上被更新的元组数的阈值超过这些阀值时分别需要执行vacuum和analyze。默认值为50个元组。
autovacuum_vacuum_scale_factor (floating point)和autovacuum_analyze_scale_factor (floating point)
设置表大小的缩放系数。
autovacuum_freeze_max_age (integer)
设置需要强制对数据库进行清理的XID上限值。
清理阈值定义为:
vacuum threshold = vacuum base threshold + vacuum scale factor * number of tuples
分析阈值定义为:
vacuum insert threshold = vacuum base insert threshold + vacuum insert scale factor * number of tuples
进程

AutoVacuum系统自动清理进程中包含两种不同的处理进程:AutoVacuum Launcher和AutoVacuum Worker。AutoVacuum Launcher进程为监控进程,用于手机数据库运行信息,根据数据库选择规则选中一个数据库,并调度一个AutoVacuum Worker进程执行清理操作。
AutoVacuum Launcher数据库选择规则:
1.数据库事务XID是32位整数递增,当XID超过配置autovacuum_freeze_max_age时强制对该DB进行清理。
2.若没有强制清理操作,则选择数据库列表中最早未执行过自动清理操作的数据库,Launcher进程会调度Worker进程去执行清理工作。
AutoVacuum Worker三种状态:
1.空闲
2.正在启动
3.运行中
源码导读
源码路径
src/backend/postmaster/autovacuum.c
/*AutoVacuum Launcher 进程*/执行流程入口函数 int StartAutoVacLauncher(void)中执行fork操作创建Postmaster的子进程AutoVacuum Launcher,在新创建的进程执行体中关闭从Postmaster进程中复制出的网络连接端口,同时进入进程AutoVacuum Launcher的执行函数体NON_EXEC_STATIC void AutoVacLauncherMain(int argc, char *argv[])。/** autovacuum启动程序的主入口点,由postmaster调用。*/int StartAutoVacLauncher(void){“伪代码逻辑”构建数据库列表,调用static void rebuild_database_list(Oid newdb){}函数a.建立一个hash表,其中每一个元素代表一个数据库。b.将pg_database平面文件中的数据结构构成一个链表。c.调用pgstat_fetch_stat_dbentry来填充每个DB节点的统计信息。d.对每个统计信息不为空的数据库,添加到Hash链表中。}
/*AutoVacuum Worker 进程*/入口函数为launch_worker函数/** launch_worker** 用于从启动程序启动辅助进程的包装器。除了实际启动它之外,* 更新数据库列表以反映下次需要在所选数据库上启动另一个列表的时间。* 实际的数据库选择留给 do_start_worker.** 如果所选数据库以前不在列表中,则此进程还将向数据库列表中插入一个条目。*/static void launch_worker(TimestampTz now){... ...}
参考
《PostgreSQL数据库内核分析》
https://www.postgresql.org/docs/current/routine-vacuuming.html#AUTOVACUUM
“德哥的视频教程”
12




