autovacuum autoanalyze代码骨架。
目录
一些概念
autovacuum、autoanalyze是后台自动触发vacuum、analyze的一套逻辑,到达了什么样的条件时,自动触发vacuum与analyze。
后台有常驻线程AVClauncher
。这个线程每隔一定的间隔会同志PM
线程来唤起一些AVCWorker
线程,由AVCWorker
进行实际的vacuum与analyze任务。
涉及到的时间间隔、唤起的worker的数量等,都有相关的GUC参数可配。
部分数据结构变量
struct WorkerInfoData
:
表示一个avcworker的结构体,存放了avcworker的一些信息、工作状态等。内部有一个SHM_QUEUE
,可以将一批worker连城一个双链表。
t_thrd.autovacuum_cxt.DatabaseList
:
AVClauncher的一个双链表,存放了数据库列表,且顺序能表示某种时间的old?来源与pgstats相关
t_thrd.autovacuum_cxt.AutoVacuumShmem
:
一块共享内存,存放一些avc的全局信息,包括一些槽位、状态等。受AutovacuumLock
保护。luncher与avcworker通过这几个槽位进行信息传递,其中主要的几个槽位有:
- av_freeWorkers:空闲的worker,是个队列。
- av_startingWorker:正在启动的worker。在这里只当成一个元素用,所以worker的启动只能是串行的,可能这样子比较安全或者实现比较简单吧。
- av_runningWorkers:正在运行的worker,是个队列。
t_thrd.autovacuum_cxt.MyWorkerInfo
:
当前worker自己的信息,存放例如正在vacuum的表。受AutovacuumScheduleLock
保护。
AVClauncher 线程: AutoVacLauncherMain()
AutoVacuumingActive(),如果没有开启autovcacuum或track_count的话,则退出。
rebuild_database_list(): 维护 t_thrd.autovacuum_cxt.DatabaseList,也是数据库的vacuum顺序。
launcher_determine_sleep() 计算sleep时间。要考虑是不是有空闲的worker,有可能所有worker都干不完活。如果没有就得多睡会。
WaitLatch 间隔sleep
ResetLatch
t_thrd.autovacuum_cxt.got_SIGHUP: 配置重加载
t_thrd.autovacuum_cxt.got_SIGUSR2:两种作用,1、avcworker完成工作通知,2、pm启动线程avcworker失败通知。然后进行相关的处理。
LWLockAcquire(AutovacuumLock, LW_SHARED);
if (t_thrd.autovacuum_cxt.AutoVacuumShmem->av_startingWorker != NULL) {
判断是不是有正在启动的avcworker。如果有且是启动时间过长的话,就LW_EXCLUSIVE,取消掉。直接重置相关槽位。
LWLockRelaese(AutovacuumLock);
如果没有 av_freeWorkers ,(同时还不能有正在启动的avcworker),全都在忙,就continue。
launch_worker(current_time) :启动一个worker {
dbid = do_start_worker() :启动一个worker {
刷新avc的统计计数信息。
dblist = get_database_list();
获取xidForceLimit,multiForceLimit。受参数autovacuum_freeze_max_age控制,表示一个事务号最多只能活多久,超过这个年龄,就得被冻结或清理。
avdb:根据dblist、DatabaseList、xidForceLimit等,选出来一个最近最少avc的或需要循环clog的、还得有统计信息的、扒拉扒拉的。
LOCK,在av_freeWorkers取出一个worker变成av_startingWorker,并将avdb、时间等信息传给特。RELEASE