本篇内容介绍了“PostgreSQL中vacuum主流程分析”的有关知识,在实际案例的操作过程中,不少人都会遇到这样的困境,接下来就让小编带领大家学习一下如何处理这些情况吧!希望大家仔细阅读,能够学有所成!

一、数据结构

宏定义
Vacuum和Analyze命令选项

/*----------------------*VacuumandAnalyzeStatements*Vacuum和Analyze命令选项**Eventhoughthesearenominallytwostatements,it'sconvenienttouse*justonenodetypeforboth.NotethatatleastoneofVACOPT_VACUUM*andVACOPT_ANALYZEmustbesetinoptions.*虽然在这里有两种不同的语句,但只需要使用统一的Node类型即可.*注意至少VACOPT_VACUUM/VACOPT_ANALYZE在选项中设置.*----------------------*/typedefenumVacuumOption{VACOPT_VACUUM=1<<0,/*doVACUUM*/VACOPT_ANALYZE=1<<1,/*doANALYZE*/VACOPT_VERBOSE=1<<2,/*printprogressinfo*/VACOPT_FREEZE=1<<3,/*FREEZEoption*/VACOPT_FULL=1<<4,/*FULL(non-concurrent)vacuum*/VACOPT_SKIP_LOCKED=1<<5,/*skipifcannotgetlock*/VACOPT_SKIPTOAST=1<<6,/*don'tprocesstheTOASTtable,ifany*/VACOPT_DISABLE_PAGE_SKIPPING=1<<7/*don'tskipanypages*/}VacuumOption;

VacuumStmt
存储vacuum命令的option&Relation链表

typedefstructVacuumStmt{NodeTagtype;//Tag//VacuumOption位标记intoptions;/*ORofVacuumOptionflags*///VacuumRelation链表,如为NIL-->所有Relation.List*rels;/*listofVacuumRelation,orNILforall*/}VacuumStmt;

VacuumParams
vacuum命令参数

/**ParameterscustomizingbehaviorofVACUUMandANALYZE.*客户端调用VACUUM/ANALYZE时的定制化参数*/typedefstructVacuumParams{//最小freezeage,-1表示使用默认intfreeze_min_age;/*minfreezeage,-1tousedefault*///扫描整个table的freezeageintfreeze_table_age;/*ageatwhichtoscanwholetable*///最小的multixactfreezeage,-1表示默认intmultixact_freeze_min_age;/*minmultixactfreezeage,-1to*usedefault*///扫描全表的freezeage,-1表示默认intmultixact_freeze_table_age;/*multixactageatwhichtoscan*wholetable*///是否强制wraparound?boolis_wraparound;/*forceafor-wraparoundvacuum*///以毫秒为单位的最小执行阈值intlog_min_duration;/*minimumexecutionthresholdinmsat*whichverboselogsareactivated,-1*tousedefault*/}VacuumParams;

VacuumRelation
VACUUM/ANALYZE命令的目标表信息

/**InfoaboutasingletargettableofVACUUM/ANALYZE.*VACUUM/ANALYZE命令的目标表信息.**IftheOIDfieldisset,italwaysidentifiesthetabletoprocess.*ThentherelationfieldcanbeNULL;ifitisn't,it'susedonlytoreport*failuretoopen/locktherelation.*如设置了OID字段,该值通常是将要处理的数据表.*那么关系字段可以为空;如果不是,则仅用于报告未能打开/锁定关系。*/typedefstructVacuumRelation{NodeTagtype;RangeVar*relation;/*tablenametoprocess,orNULL*/Oidoid;/*table'sOID;InvalidOidifnotlookedup*/List*va_cols;/*listofcolumnnames,orNILforall*/}VacuumRelation;二、源码解读

ExecVacuum函数,手工执行VACUUM/ANALYZE命令时的主入口,vacuum()函数的包装器(wrapper).

/**PrimaryentrypointformanualVACUUMandANALYZEcommands*手工执行VACUUM/ANALYZE命令时的主入口**Thisismainlyapreparationwrapperfortherealoperationsthatwill*happeninvacuum().*这是vacuum()函数的包装器(wrapper)*/voidExecVacuum(VacuumStmt*vacstmt,boolisTopLevel){VacuumParamsparams;/*sanitychecksonoptions*///验证&检查Assert(vacstmt->options&(VACOPT_VACUUM|VACOPT_ANALYZE));Assert((vacstmt->options&VACOPT_VACUUM)||!(vacstmt->options&(VACOPT_FULL|VACOPT_FREEZE)));Assert(!(vacstmt->options&VACOPT_SKIPTOAST));/**MakesureVACOPT_ANALYZEisspecifiedifanycolumnlistsarepresent.*如出现字段列表,则确保指定了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("ANALYZEoptionmustbespecifiedwhenacolumnlistisprovided")));}}/**AllfreezeagesarezeroiftheFREEZEoptionisgiven;otherwisepass*themas-1whichmeanstousethedefaultvalues.*如指定了FREEZE选项则设置所有freezeages为0.*否则的话,传递-1(即使用默认值).*/if(vacstmt->options&VACOPT_FREEZE){//指定VACOPT_FREEZEparams.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-invokedvacuumisnever"forwraparound"*///用户调用的vacuum永远不会是wraparoundparams.is_wraparound=false;/*user-invokedvacuumneverusesthisparameter*///用户调用vacuum永远不会使用该参数params.log_min_duration=-1;/*Nowgothroughthecommonroutine*///调用vacuumvacuum(vacstmt->options,vacstmt->rels,&params,NULL,isTopLevel);}三、跟踪分析

测试脚本

17:19:28(xdb@[local]:5432)testdb=#vacuumt1;

启动gdb,设置断点

(gdb)bExecVacuumBreakpoint1at0x6b99a1:filevacuum.c,line92.(gdb)cContinuing.Breakpoint1,ExecVacuum(vacstmt=0x210e9c0,isTopLevel=true)atvacuum.c:9292Assert(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)n93Assert((vacstmt->options&VACOPT_VACUUM)||(gdb)95Assert(!(vacstmt->options&VACOPT_SKIPTOAST));(gdb)100if(!(vacstmt->options&VACOPT_ANALYZE))(gdb)104foreach(lc,vacstmt->rels)(gdb)106VacuumRelation*vrel=lfirst_node(VacuumRelation,lc);(gdb)108if(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)n104foreach(lc,vacstmt->rels)(gdb)119if(vacstmt->options&VACOPT_FREEZE)(gdb)128params.freeze_min_age=-1;(gdb)129params.freeze_table_age=-1;(gdb)130params.multixact_freeze_min_age=-1;(gdb)131params.multixact_freeze_table_age=-1;(gdb)135params.is_wraparound=false;(gdb)(gdb)n138params.log_min_duration=-1;(gdb)

调用vacuum

141vacuum(vacstmt->options,vacstmt->rels,&params,NULL,isTopLevel);(gdb)142}(gdb)standard_ProcessUtility(pstmt=0x210ea80,queryString=0x210dec8"vacuumt1;",context=PROCESS_UTILITY_TOPLEVEL,params=0x0,queryEnv=0x0,dest=0x210ed70,completionTag=0x7fff1d69dea0"")atutility.c:672672break;

“PostgreSQL中vacuum主流程分析”的内容就介绍到这里了,感谢大家的阅读。如果想了解更多行业相关的知识可以关注亿速云网站,小编将为大家输出更多高质量的实用文章!