本篇内容介绍了“PostgreSQL中vacuum主流程分析”的有关知识,在实际案例的操作过程中,不少人都会遇到这样的困境,接下来就让小编带领大家学习一下如何处理这些情况吧!希望大家仔细阅读,能够学有所成!
宏定义
Vacuum和Analyze命令选项
/* ---------------------- * Vacuum and Analyze Statements * Vacuum和Analyze命令选项 * * Even though these are nominally two statements, it's convenient to use * just one node type for both. Note that at least one of VACOPT_VACUUM * and VACOPT_ANALYZE must be set in options. * 虽然在这里有两种不同的语句,但只需要使用统一的Node类型即可. * 注意至少VACOPT_VACUUM/VACOPT_ANALYZE在选项中设置. * ---------------------- */ typedef enum VacuumOption { VACOPT_VACUUM = 1 << 0, /* do VACUUM */ VACOPT_ANALYZE = 1 << 1, /* do ANALYZE */ VACOPT_VERBOSE = 1 << 2, /* print progress info */ VACOPT_FREEZE = 1 << 3, /* FREEZE option */ VACOPT_FULL = 1 << 4, /* FULL (non-concurrent) vacuum */ VACOPT_SKIP_LOCKED = 1 << 5, /* skip if cannot get lock */ VACOPT_SKIPTOAST = 1 << 6, /* don't process the TOAST table, if any */ VACOPT_DISABLE_PAGE_SKIPPING = 1 << 7 /* don't skip any pages */ } VacuumOption;
VacuumStmt
存储vacuum命令的option&Relation链表
typedef struct VacuumStmt { NodeTag type;//Tag //VacuumOption位标记 int options; /* OR of VacuumOption flags */ //VacuumRelation链表,如为NIL-->所有Relation. List *rels; /* list of VacuumRelation, or NIL for all */ } VacuumStmt;
VacuumParams
vacuum命令参数
/* * Parameters customizing behavior of VACUUM and ANALYZE. * 客户端调用VACUUM/ANALYZE时的定制化参数 */ typedef struct VacuumParams { //最小freeze age,-1表示使用默认 int freeze_min_age; /* min freeze age, -1 to use default */ //扫描整个table的freeze age int freeze_table_age; /* age at which to scan whole table */ //最小的multixact freeze age,-1表示默认 int multixact_freeze_min_age; /* min multixact freeze age, -1 to * use default */ //扫描全表的freeze age,-1表示默认 int multixact_freeze_table_age; /* multixact age at which to scan * whole table */ //是否强制wraparound? bool is_wraparound; /* force a for-wraparound vacuum */ //以毫秒为单位的最小执行阈值 int log_min_duration; /* minimum execution threshold in ms at * which verbose logs are activated, -1 * to use default */ } VacuumParams;
VacuumRelation
VACUUM/ANALYZE命令的目标表信息
/* * Info about a single target table of VACUUM/ANALYZE. * VACUUM/ANALYZE命令的目标表信息. * * If the OID field is set, it always identifies the table to process. * Then the relation field can be NULL; if it isn't, it's used only to report * failure to open/lock the relation. * 如设置了OID字段,该值通常是将要处理的数据表. * 那么关系字段可以为空;如果不是,则仅用于报告未能打开/锁定关系。 */ 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;
ExecVacuum函数,手工执行VACUUM/ANALYZE命令时的主入口,vacuum()函数的包装器(wrapper).
/* * Primary entry point for manual VACUUM and ANALYZE commands * 手工执行VACUUM/ANALYZE命令时的主入口 * * This is mainly a preparation wrapper for the real operations that will * happen in vacuum(). * 这是vacuum()函数的包装器(wrapper) */ void ExecVacuum(VacuumStmt *vacstmt, bool isTopLevel) { VacuumParams params; /* sanity checks on options */ //验证&检查 Assert(vacstmt->options & (VACOPT_VACUUM | VACOPT_ANALYZE)); Assert((vacstmt->options & VACOPT_VACUUM) || !(vacstmt->options & (VACOPT_FULL | VACOPT_FREEZE))); Assert(!(vacstmt->options & VACOPT_SKIPTOAST)); /* * Make sure VACOPT_ANALYZE is specified if any column lists are present. * 如出现字段列表,则确保指定了VACOPT_ANALYZE选项 */ if (!(vacstmt->options & VACOPT_ANALYZE)) { ListCell *lc; foreach(lc, vacstmt->rels) { VacuumRelation *vrel = lfirst_node(VacuumRelation, lc); if (vrel->va_cols != NIL) ereport(ERROR, (errcode(ERRCODE_FEATURE_NOT_SUPPORTED), errmsg("ANALYZE option must be specified when a column list is provided"))); } } /* * All freeze ages are zero if the FREEZE option is given; otherwise pass * them as -1 which means to use the default values. * 如指定了FREEZE选项则设置所有freeze ages为0. * 否则的话,传递-1(即使用默认值). */ if (vacstmt->options & VACOPT_FREEZE) { //指定VACOPT_FREEZE params.freeze_min_age = 0; params.freeze_table_age = 0; params.multixact_freeze_min_age = 0; params.multixact_freeze_table_age = 0; } else { params.freeze_min_age = -1; params.freeze_table_age = -1; params.multixact_freeze_min_age = -1; params.multixact_freeze_table_age = -1; } /* user-invoked vacuum is never "for wraparound" */ //用户调用的vacuum永远不会是wraparound params.is_wraparound = false; /* user-invoked vacuum never uses this parameter */ //用户调用vacuum永远不会使用该参数 params.log_min_duration = -1; /* Now go through the common routine */ //调用vacuum vacuum(vacstmt->options, vacstmt->rels, ¶ms, NULL, isTopLevel); }
测试脚本
17:19:28 (xdb@[local]:5432)testdb=# vacuum t1;
启动gdb,设置断点
(gdb) b ExecVacuum Breakpoint 1 at 0x6b99a1: file vacuum.c, line 92. (gdb) c Continuing. Breakpoint 1, ExecVacuum (vacstmt=0x210e9c0, isTopLevel=true) at vacuum.c:92 92 Assert(vacstmt->options & (VACOPT_VACUUM | VACOPT_ANALYZE)); (gdb)
输入参数
options = 1 —> VACOPT_VACUUM
(gdb) p *vacstmt $1 = {type = T_VacuumStmt, options = 1, rels = 0x210e988} (gdb)
获取Relation相关信息
gdb) n 93 Assert((vacstmt->options & VACOPT_VACUUM) || (gdb) 95 Assert(!(vacstmt->options & VACOPT_SKIPTOAST)); (gdb) 100 if (!(vacstmt->options & VACOPT_ANALYZE)) (gdb) 104 foreach(lc, vacstmt->rels) (gdb) 106 VacuumRelation *vrel = lfirst_node(VacuumRelation, lc); (gdb) 108 if (vrel->va_cols != NIL) (gdb) p *vrel $3 = {type = T_VacuumRelation, relation = 0x210e8d0, oid = 0, va_cols = 0x0} (gdb) p *vrel->relation $4 = {type = T_RangeVar, catalogname = 0x0, schemaname = 0x0, relname = 0x210e8b0 "t1", inh = true, relpersistence = 112 'p', alias = 0x0, location = 7} (gdb)
设置vacuum参数
(gdb) n 104 foreach(lc, vacstmt->rels) (gdb) 119 if (vacstmt->options & VACOPT_FREEZE) (gdb) 128 params.freeze_min_age = -1; (gdb) 129 params.freeze_table_age = -1; (gdb) 130 params.multixact_freeze_min_age = -1; (gdb) 131 params.multixact_freeze_table_age = -1; (gdb) 135 params.is_wraparound = false; (gdb) (gdb) n 138 params.log_min_duration = -1; (gdb)
调用vacuum
141 vacuum(vacstmt->options, vacstmt->rels, ¶ms, NULL, isTopLevel); (gdb) 142 } (gdb) standard_ProcessUtility (pstmt=0x210ea80, queryString=0x210dec8 "vacuum t1;", context=PROCESS_UTILITY_TOPLEVEL, params=0x0, queryEnv=0x0, dest=0x210ed70, completionTag=0x7fff1d69dea0 "") at utility.c:672 672 break;
“PostgreSQL中vacuum主流程分析”的内容就介绍到这里了,感谢大家的阅读。如果想了解更多行业相关的知识可以关注亿速云网站,小编将为大家输出更多高质量的实用文章!
免责声明:本站发布的内容(图片、视频和文字)以原创、转载和分享为主,文章观点不代表本网站立场,如果涉及侵权请联系站长邮箱:is@yisu.com进行举报,并提供相关证据,一经查实,将立刻删除涉嫌侵权内容。