Postgresql内核源码分析-vacuum流程

 

  • 专栏内容: postgresql内核源码分析​​​​​​​
  • 个人主页:senllang的主页
  • 座右铭:天行健,君子以自强不息;地势坤,君子以厚德载物.

文章目录

  • 前言
  • 概要介绍
  • 入口函数
  • 清理数据流程
  • analyze流程
  • 事务号冻结流程
  • 结尾

前言

本文是基于postgresql 15的代码进行分析解读,演示是在centos8系统上进行。


  • 一.概要介绍

postgresql的MVCC机制,在update时会产生新旧版本,而且存储在表文件中,导致表数据膨胀,影响查询扫描的效率。vacuum的引入就是定期对deadtuple的清理,所谓deadtuple,对所有事务来说都是过期版本。

下面详细介绍vacuum具体做那些事情,以及如何来展,在清理过程中又是怎么避免与业务的冲突。

  • 二.入口函数

    • 以多种形式执行vacuum,如sql命令,vacuumdb命令,还有后台自动执行的autovacuum服务,它们经过各自己的包装处理后,都由vacuum()来统一处理
void

vacuum(List *relations, VacuumParams *params,

       BufferAccessStrategy bstrategy, bool isTopLevel)

  • 参数说明

    • relations ,待处理的relation列表,如果为空,就处理当前数据库的所有表;
    • params,记录执行vacuum的参数,主要是行为的可选,如是否为full, 是否跳过冲突的page等等,详细说明参见 vacuum命令的分析;
    • bstrategy, 在autovacuum时会传入,其它情况下都为NULL
    • isTopLevel,由 ProcessUtility 调用时传入 ,istopleve取值如下:
typedef enum

{

    PROCESS_UTILITY_TOPLEVEL,   /* toplevel interactive command */

    PROCESS_UTILITY_QUERY,      /* a complete query, but not toplevel */

    PROCESS_UTILITY_QUERY_NONATOMIC,    /* a complete query, nonatomic

                                         * execution context */

    PROCESS_UTILITY_SUBCOMMAND  /* a portion of a query */

} ProcessUtilityContext;

  • 函数流程

    • 检查事务,对于analyze是需在处在事务中,对于vacuum,不能已经处于事务中,因为它自己会启动事务;
    • 检查表列表,如果没有指定,获取所有表的列表
    • 分配全局内存上下文,可能会多次使用;
static MemoryContext vac_context = NULL;

static BufferAccessStrategy vac_strategy;

  • 如果使用自己的事务,就需要结束backend启动时的事务;
  • vacuum的 表的vacuum和analyze整个处理放在 try…catch 当中,具有原子操作
  • 在上面处理结束后,进行事务号冻结处理
  • 最后释放内存上下文,结束处理

  • 三.清理数据流程

    • 处理函数为  vacuum_rel
    • 参数说明
      • OID, 待处理的relation OID
      • relation RangeVar类型,对应OID的表信息

typedef struct RangeVar

{

    NodeTag     type;

    /* the catalog (database) name, or NULL */

    char       *catalogname;

    /* the schema name, or NULL */

    char       *schemaname;

    /* the relation/sequence name */

    char       *relname;

    /* expand rel by inheritance? recursively act on children? */

    bool        inh;

    /* see RELPERSISTENCE_* in pg_class.h */

    char        relpersistence;

    /* table alias & optional column aliases */

    Alias      *alias;

    /* token location, or -1 if unknown */

    int         location;

} RangeVar;

前两个参数都是从VacuumRelation结构体中得来,也就是relation的List;

typedef struct VacuumRelation

{

    NodeTag     type;

    RangeVar   *relation;       /* table name to process, or NULL */

    Oid         oid;            /* table's OID; InvalidOid if not looked up */

    List       *va_cols;        /* list of column names, or NIL for all */

} VacuumRelation;

  • 启动事务
  • 处理vacuum ,分两种类型
    • Layze vacuum 由 table_relation_vacuum执行,由SQL命令和autovacuum触发

static inline void

table_relation_vacuum(Relation rel, struct VacuumParams *params,

                      BufferAccessStrategy bstrategy)

在执行时,持有表锁为 ShareUpdateExclusive lock

  • Full vacuum 由 cluster_rel 执行

/* VACUUM FULL is now a variant of CLUSTER; see cluster.c */

void cluster_rel(Oid tableOid, Oid indexOid, ClusterParams *params);

在执行时,执有最高级别表锁

  • 四.analyze流程

    • 处理函数为  analyze_rel

  • 五.事务号冻结流程

    • 处理函数为 vac_update_datfrozenxid

结尾

作者邮箱:[email protected]
如有错误或者疏漏欢迎指出,互相学习。

注:未经同意,不得转载!

猜你喜欢

转载自blog.csdn.net/senllang/article/details/128890884