greenplum 中的 vacuum

vaccum 函数

exec_simple_query->PortalRun->PortalRunMulti->PortalRunUtility->ProcessUtility->standard_ProcessUtility->vacuum 逻辑。

  1. 检验这个 vacuum 命令不是在事务块中执行的
  2. 统计 pg_database 中所有 dead 的 database 通知 collector 去 drop 这些 database,统计自己用户的 database 中 pg_class 的所有表和 pg_proc 的所有 functions,报告给 collector。
  3. 创建 vacuum 用的上下文
  4. 对dispatcher,为了快速释放锁,需要提交当前事务(不在事务中执行vacuum),但executor不提交事务。
  5. 对每个表执行 vacuumStatement_Relation
  6. 重新开启事务去对应postgresMain中的结束事务。
  7. 更新 frozen xid 并 truncate pg_clog

vacuumStatement_Relation

  1. 获取当前的快照(PushActiveSnapshot(GetTransactionSnapshot())
  2. 打开表,检查有没有权限执行 vacuum,及是否是可清理的表(外表,特殊系统表,非表不可以清理)
  3. 不能清理其它namespace的临时表(其它backend)
  4. 获取session级别的锁(以此保证清理toast表时,其主表不会更改)
  5. 将 vaccum parenttable 或 vaccum database 相关的具体表展开(vacuumStatement_AssignRelation)
  6. 执行清理 vacuum_rel
  7. 对于 append only 表使用复制的方式清理旧元组
  8. 释放 session 锁

vacuum_rel

  1. 记录下这个表的 toast 和 append only 的 segment。
  2. 切换至表的创建用户(用于执行表的索引函数)
  3. 保存现有的全局变量 NewGUCNestLevel()
  4. 对于 dispatcher,打开所有可以vaccum的索引,要加共享锁,并分发出去(dispatchVacuum)并更新统计(vac_update_relstats_from_list)
  5. 对于executor,执行 lazy vacuum(lazy_vacuum_rel
  6. 还原全局变量 (AtEOXact_GUC)
  7. 切换回原用户(SetUserIdAndSecContext)
  8. 在dispatcher,对 append only 表重新统计压缩或 drop 后的元组数 (UpdateMasterAosegTotalsFromSegments)
  9. 关闭表
  10. dispatcher 提交这一次vacuum事务
  11. dispatcher 继续清理相关 toast 表(还持有着session锁,因此可以做这一步)
  12. dispatcher 继续清理append only 表的 segment 表,block directory 表还有 visimap 表。

lazy_vacuum_rel

  1. 更新 oldest-Xmin,计算新的可以 freeze 的 xid 位置
  2. 对 append only 表可优化执行 (因为不存在更新链,所以可以直接标记live或dead,lazy_vacuum_aorel
  3. 打开表的所有索引
  4. 执行 vaccum (lazy_scan_heap)
    1. 跳过元组全可见的页(没有修改过)
    2. 检查是否有中断和是否到了该休息一下的时候
    3. pin 页可见性统计页
    4. 读入一页
    5. 获取这页的锁
    6. 如果获取不成功,但是没有到为防止事务号回卷而必须值全表清理的程度,就可以先跳过这一页
    7. 如果读入的是新页,可能这一页还没被读入这页的进程初始化,我们放弃一次锁再重新获取,如果还是没初始化,那这个进程可能死掉了,我们可以自己把这页初始化
    8. 收集和清理过老的元组,统计页中被清理的元组数(heap_page_prune
      1. 读每个itemid并找到相关的更新链条,执行 heap_prune_chain
        1. 跳过itemid上标记 unused,redirected,dead的元组
        2. 判断这一个元组对所有事务可见 HeapTupleSatisfiesVacuum
        3. 更新本页最小事务号
        4. 更新一条链的起始位置到pstate的redirect数组上,如果一条链全删除了,就更新到pstate的dead数组上
      2. heap_page_prune_execute
        1. 将 redirect 的元组位置更新到对应的根 itemid 上
        2. 将 dead 的元组位置更新到对应的 itemid 上
        3. 将所有未使用的元组位置更新到对应的 itemid 上
        4. 将元组数据压缩到一起(清除中间的碎片PageRepairFragmentation
      3. 写 XLOG_HEAP2_CLEAN 的事务日志
      4. 更新页的 lsn
      5. 更新表中元组的统计信息 (pgstat_update_heap_dead_tuples)
    9. 再次扫描标记frozen元组,同时清理新dead的元组
      1. 对死亡的itemid做标记
      2. 对未死亡元组判断是否需要freeze(heap_execute_freeze_tuple),写 XLOG_HEAP2_FREEZE_PAGE 日志
      3. 标记 all_visible,如果此页全可见了
      4. 如果发现了 dead 元组,就清除 all_visible 标记
      5. 累加非空页的页数
      6. 记录空闲空间
      7. 先移除索引(lazy_vacuum_index),再清理页(lazy_vacuum_heap
      8. 更新索引上的统计(lazy_cleanup_index
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值