作者:bytehouse
Oracle ACE、PostgreSQL ACE
10+年数据库架构与运维实战经验
公众号:bytehouse
墨天轮专栏:bytehouse
CSDN:Young DBA  

一、视图官方定义

pg_stat_autovacuum_scores 是PostgreSQL内置系统视图,为当前数据库中的每个表(包含TOAST表)返回一行数据,展示表的自动清理(autovacuum)实时分数;autovacuum会基于分数优先级处理表,分数越高,清理优先级越高

该视图同时标识autovacuum是否会对表执行VACUUM清理、ANALYZE分析,以及表是否存在事务ID回卷风险。

该视图的计算逻辑与autovacuum工作进程完全一致,但使用实时数据源;而autovacuum工作进程会预加载待处理表列表,两者数据源可能存在差异。因此,该视图无法100%准确预测autovacuum的处理对象和执行顺序,仅作为参考依据。

This view contains one row for each table in the current database, showing the current autovacuum scores for that specific table.  It also shows whether autovacuum would vacuum or analyze the table. 
​
view shows the current scores of all tables in the current database.
​
One row for each table in the current database, showing the current autovacuum scores for that specific table.  See pg_stat_autovacuum_scores  for details.
​
The pg_stat_autovacuum_scores  view will contain one row for each table in the current database (including TOAST tables), showing the current autovacuum scores for that specific table.  Autovacuum prioritizes tables deemed eligible for processing based on their score, with higher scores indicating higher priority.  See for more information.
​
While this view generates its results the same way that autovacuum workers do, it does so using the current source information, which might differ from the source information that an autovacuum worker sees when it gathers its list of tables to process.  Therefore, this view is not a completely reliable indicator of which tables autovacuum will process and what order it will process them.

二、视图SQL定义

CREATE VIEW pg_stat_autovacuum_scores AS
    SELECT
        s.oid AS relid,
        n.nspname AS schemaname,
        c.relname AS relname,
        s.score,
        s.xid_score,
        s.mxid_score,
        s.vacuum_score,
        s.vacuum_insert_score,
        s.analyze_score,
        s.do_vacuum,
        s.do_analyze,
        s.for_wraparound
    FROM pg_stat_get_autovacuum_scores() s
    JOIN pg_class c on c.oid = s.oid
    LEFT JOIN pg_namespace n ON n.oid = c.relnamespace;

三、视图字段说明

字段名 类型 含义
relid oid 表的唯一对象标识符(OID)
schemaname name 表所属模式名称
relname name 表名称
score float8 总优先级分数(所有子分数最大值)
xid_score float8 事务ID老化分数(基于事务ID冻结阈值)
mxid_score float8 多事务ID老化分数(基于多事务冻结阈值)
vacuum_score float8 常规VACUUM分数(基于死元组、更新/删除量)
vacuum_insert_score float8 插入清理分数(基于批量插入数据量)
analyze_score float8 ANALYZE分析分数(基于数据变更行数阈值)
do_vacuum bool 是否需要执行VACUUM清理
do_analyze bool 是否需要执行ANALYZE分析
for_wraparound bool 是否因事务ID回卷风险需要强制清理

PostgreSQL的autovacuum不是随机执行,而是基于分数排序处理表,这个视图完全复刻了autovacuum worker的评分逻辑,评分维度包含6大核心指标:

分数字段 含义 计算依据
score 总优先级分数(最大值) 所有子分数的最高值,决定最终优先级
xid_score 事务ID老化分数 表的事务ID距离冻结阈值的时长
mxid_score 多事务ID老化分数 多事务ID距离冻结阈值的时长
vacuum_score 常规VACUUM分数 表的死元组数量、更新删除量
vacuum_insert_score 插入清理分数 表的批量插入数据量
analyze_score ANALYZE分析分数 表的数据变更行数阈值

关键判断标识

  1. do_vacuum:布尔值,true表示表满足条件,需要执行VACUUM

  2. do_analyze:布尔值,true表示表满足条件,需要执行ANALYZE

  3. for_wraparound:布尔值,true表示表存在事务ID回卷风险,必须强制清理(数据库防崩溃机制)。

相关视图:

  • pg_stat_xact_user_tables

  • pg_statio_all_tables

四、内核核心函数:pg_stat_get_autovacuum_scores

该C函数是视图的数据计算核心,完全复刻autovacuum的评分与判断逻辑,遍历数据库表并计算清理分数、判断清理需求。

+/*
+ * pg_stat_get_autovacuum_scores
+ *
+ * Returns current autovacuum scores for all relevant tables in the current
+ * database.
+ */
+Datum
+pg_stat_get_autovacuum_scores(PG_FUNCTION_ARGS)
+{
+   int         effective_multixact_freeze_max_age;
+   Relation    rel;
+   TableScanDesc scan;
+   HeapTuple   tup;
+   ReturnSetInfo *rsinfo = (ReturnSetInfo *) fcinfo->resultinfo;
+
+   InitMaterializedSRF(fcinfo, 0);
+
+   /* some prerequisite initialization */
+   effective_multixact_freeze_max_age = MultiXactMemberFreezeThreshold();
+   recentXid = ReadNextTransactionId();
+   recentMulti = ReadNextMultiXactId();
+
+   /* scan pg_class */
+   rel = table_open(RelationRelationId, AccessShareLock);
+   scan = table_beginscan_catalog(rel, 0, NULL);
+   while ((tup = heap_getnext(scan, ForwardScanDirection)) != NULL)
+   {
+       Form_pg_class form = (Form_pg_class) GETSTRUCT(tup);
+       AutoVacOpts *avopts;
+       bool        dovacuum;
+       bool        doanalyze;
+       bool        wraparound;
+       AutoVacuumScores scores;
+       Datum       vals[10];
+       bool        nulls[10] = {false};
+
+       /* skip ineligible entries */
+       if (form->relkind != RELKIND_RELATION &&
+           form->relkind != RELKIND_MATVIEW &&
+           form->relkind != RELKIND_TOASTVALUE)
+           continue;
+       if (form->relpersistence == RELPERSISTENCE_TEMP)
+           continue;
+
+       avopts = extract_autovac_opts(tup, RelationGetDescr(rel));
+       relation_needs_vacanalyze(form->oid, avopts, form,
+                                 effective_multixact_freeze_max_age, 0,
+                                 &dovacuum, &doanalyze, &wraparound,
+                                 &scores);
+       if (avopts)
+           pfree(avopts);
+
+       vals[0] = ObjectIdGetDatum(form->oid);
+       vals[1] = Float8GetDatum(scores.max);
+       vals[2] = Float8GetDatum(scores.xid);
+       vals[3] = Float8GetDatum(scores.mxid);
+       vals[4] = Float8GetDatum(scores.vac);
+       vals[5] = Float8GetDatum(scores.vac_ins);
+       vals[6] = Float8GetDatum(scores.anl);
+       vals[7] = BoolGetDatum(dovacuum);
+       vals[8] = BoolGetDatum(doanalyze);
+       vals[9] = BoolGetDatum(wraparound);
+
+       tuplestore_putvalues(rsinfo->setResult, rsinfo->setDesc, vals, nulls);
+   }
+   table_endscan(scan);
+   table_close(rel, AccessShareLock);
+
+   return (Datum) 0;
+}

这是视图的核心计算逻辑,完全复刻autovacuum worker的判断逻辑,分步解析:

(1)初始化环境
effective_multixact_freeze_max_age = MultiXactMemberFreezeThreshold();
recentXid = ReadNextTransactionId();
recentMulti = ReadNextMultiXactId();
  • 获取多事务冻结阈值最新事务ID最新多事务ID

  • 这些是计算表老化程度、分数的基础参数。

(2)扫描系统表pg_class

遍历数据库中所有表的元数据,筛选符合清理条件的表

if (form->relkind != RELKIND_RELATION &&
    form->relkind != RELKIND_MATVIEW &&
    form->relkind != RELKIND_TOASTVALUE)
    continue;
if (form->relpersistence == RELPERSISTENCE_TEMP)
    continue;

筛选规则

  • 仅保留:普通表、物化视图、TOAST系统表;

  • 跳过临时表(autovacuum不处理临时表)。

(3)核心计算:判断是否需要清理+计算分数
avopts = extract_autovac_opts(tup, RelationGetDescr(rel));
relation_needs_vacanalyze(
    form->oid, avopts, form,
    effective_multixact_freeze_max_age, 0,
    &dovacuum, &doanalyze, &wraparound,
    &scores
);
  • extract_autovac_opts:提取表的自定义autovacuum配置(优先级高于全局配置);

  • relation_needs_vacanalyze内核核心函数,计算所有分数、判断是否需要清理/分析/回卷保护。

(4)返回结果集

将计算好的OID、分数、布尔标识,组装为结果集返回给SQL视图。

Logo

腾讯云面向开发者汇聚海量精品云计算使用和开发经验,营造开放的云计算技术生态圈。

更多推荐