iis服务器助手广告广告
返回顶部
首页 > 资讯 > 数据库 >PostgreSQL中vacuum过程分析
  • 195
分享到

PostgreSQL中vacuum过程分析

2024-04-02 19:04:59 195人浏览 独家记忆
摘要

本篇内容主要讲解“postgresql中vacuum过程分析”,感兴趣的朋友不妨来看看。本文介绍的方法操作简单快捷,实用性强。下面就让小编来带大家学习“Postgresql中vacuum过程分析”吧!一、数

本篇内容主要讲解“postgresql中vacuum过程分析”,感兴趣的朋友不妨来看看。本文介绍的方法操作简单快捷,实用性强。下面就让小编来带大家学习“Postgresql中vacuum过程分析”吧!

一、数据结构

宏定义
Vacuum和Analyze命令选项


typedef enum VacuumOption
{
    VACOPT_VACUUM = 1 << 0,     
    VACOPT_ANALYZE = 1 << 1,    
    VACOPT_VERBOSE = 1 << 2,    
    VACOPT_FREEZE = 1 << 3,     
    VACOPT_FULL = 1 << 4,       
    VACOPT_SKIP_LOCKED = 1 << 5,    
    VACOPT_SKIPTOAST = 1 << 6,  
    VACOPT_DISABLE_PAGE_SKIPPING = 1 << 7   
} VacuumOption;

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

typedef struct VacuumStmt
{
    nodeTag     type;//Tag
    //VacuumOption位标记
    int         options;        
    //VacuumRelation链表,如为NIL-->所有Relation.
    List       *rels;           
} VacuumStmt;

VacuumParams
vacuum命令参数


typedef struct VacuumParams
{
    //最小freeze age,-1表示使用默认
    int         freeze_min_age; 
    //扫描整个table的freeze age
    int         freeze_table_age;   
    //最小的multixact freeze age,-1表示默认
    int         multixact_freeze_min_age;   
    //扫描全表的freeze age,-1表示默认
    int         multixact_freeze_table_age; 
    //是否强制wraparound?
    bool        is_wraparound;  
    //以毫秒为单位的最小执行阈值
    int         log_min_duration;   
} VacuumParams;

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


typedef struct VacuumRelation
{
    NodeTag     type;
    RangeVar   *relation;       
    Oid         oid;            
    List       *va_cols;        
} VacuumRelation;

二、源码解读

vacuum是VACUUM/ANALYZE命令的内部处理入口.
逻辑比较简单:
1.配置vacuum处理的相关参数,如命令类型等
2.执行相关检查
3.构造vacuum处理上下文
4.构造vacuum需处理的relation链表
5.循环遍历relation链表
 5.1 获取relation
 5.2 执行vacuum_rel
6.收尾工作


void
vacuum(int options, List *relations, VacuumParams *params,
       BufferAccessStrategy bstrategy, bool isTopLevel)
{
    static bool in_vacuum = false;//是否在vacuum
    const char *stmttype;//语句类型,vacuum?analyze?
    volatile bool in_outer_xact,
                use_own_xacts;
    Assert(params != NULL);
    stmttype = (options & VACOPT_VACUUM) ? "VACUUM" : "ANALYZE";
    
    if (options & VACOPT_VACUUM)
    {
        PreventInTransactionBlock(isTopLevel, stmttype);
        in_outer_xact = false;
    }
    else
        in_outer_xact = IsInTransactionBlock(isTopLevel);
    
    if (in_vacuum)
        ereport(ERROR,
                (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
                 errmsg("%s cannot be executed from VACUUM or ANALYZE",
                        stmttype)));
    
    if ((options & VACOPT_FULL) != 0 &&
        (options & VACOPT_DISABLE_PAGE_SKIPPING) != 0)
        ereport(ERROR,
                (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
                 errmsg("VACUUM option DISABLE_PAGE_SKIPPING cannot be used with FULL")));
    
    if ((options & VACOPT_VACUUM) && !IsAutoVacuumWorkerProcess())
        pgstat_vacuum_stat();
    
    vac_context = AllocSetContextCreate(PortalContext,
                                        "Vacuum",
                                        ALLOCSET_DEFAULT_SIZES);
    
    if (bstrategy == NULL)
    {
        MemoryContext old_context = MemoryContextSwitchTo(vac_context);
        bstrategy = GetAccessStrategy(BAS_VACUUM);
        MemoryContextSwitchTo(old_context);
    }
    vac_strategy = bstrategy;
    
    if (relations != NIL)
    {
        List       *newrels = NIL;
        ListCell   *lc;
        foreach(lc, relations)
        {
            VacuumRelation *vrel = lfirst_node(VacuumRelation, lc);
            List       *sublist;
            MemoryContext old_context;
            sublist = expand_vacuum_rel(vrel, options);
            old_context = MemoryContextSwitchTo(vac_context);
            newrels = list_concat(newrels, sublist);
            MemoryContextSwitchTo(old_context);
        }
        relations = newrels;
    }
    else
        relations = get_all_vacuum_rels(options);
    
    if (options & VACOPT_VACUUM)
        use_own_xacts = true;
    else
    {
        Assert(options & VACOPT_ANALYZE);
        if (IsAutoVacuumWorkerProcess())
            use_own_xacts = true;
        else if (in_outer_xact)
            use_own_xacts = false;
        else if (list_length(relations) > 1)
            use_own_xacts = true;
        else
            use_own_xacts = false;
    }
    
    if (use_own_xacts)
    {
        Assert(!in_outer_xact);
        
        //autovacuum不会设置ActiveSnapshot
        if (ActiveSnapshotSet())
            PopActiveSnapshot();
        
        //匹配PostgresMain()中的StartTransaction
        CommitTransactionCommand();
    }
    
    //设置vacuum成本计数on/off,并set/clear in_vacuum参数
    PG_TRY();
    {
        ListCell   *cur;
        in_vacuum = true;
        VacuumCostActive = (VacuumCostDelay > 0);
        VacuumCostBalance = 0;
        VacuumPageHit = 0;
        VacuumPageMiss = 0;
        VacuumPageDirty = 0;
        
        foreach(cur, relations)
        {
            VacuumRelation *vrel = lfirst_node(VacuumRelation, cur);
            if (options & VACOPT_VACUUM)
            {
                //执行vacuum处理
                if (!vacuum_rel(vrel->oid, vrel->relation, options, params))
                    continue;
            }
            if (options & VACOPT_ANALYZE)
            {
                
                if (use_own_xacts)
                {
                    //使用自己的事务
                    StartTransactionCommand();
                    
                    //快照压栈
                    PushActiveSnapshot(GetTransactionSnapshot());
                }
                //分析relation
                analyze_rel(vrel->oid, vrel->relation, options, params,
                            vrel->va_cols, in_outer_xact, vac_strategy);
                if (use_own_xacts)
                {
                    //使用自己的事务,出栈
                    PopActiveSnapshot();
                    //提交事务
                    CommitTransactionCommand();
                }
            }
        }
    }
    PG_CATCH();
    {
        in_vacuum = false;
        VacuumCostActive = false;
        PG_RE_THROW();
    }
    PG_END_TRY();
    in_vacuum = false;
    VacuumCostActive = false;
    
    if (use_own_xacts)
    {
        
        //在这里,没有处于事务中
        
        StartTransactionCommand();
    }
    if ((options & VACOPT_VACUUM) && !IsAutoVacuumWorkerProcess())
    {
        
        vac_update_datfrozenxid();
    }
    
    MemoryContextDelete(vac_context);
    vac_context = NULL;
}

三、跟踪分析

测试脚本

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

启动gdb,设置断点

(gdb) b vacuum
Breakpoint 1 at 0x6b9b8c: file vacuum.c, line 175.
(gdb) c
Continuing.
Breakpoint 1, vacuum (options=1, relations=0x2294988, params=0x7fff403D8880, bstrategy=0x0, isTopLevel=true) at vacuum.c:175
175     Assert(params != NULL);
(gdb)

输入参数
options=1 —> VACOPT_VACUUM
relations=0x2294988,relation链表,里面只有一个item,即t1
params=0x7fff403d8880,默认参数
bstrategy=NULL,
isTopLevel=T,为顶层事务

(gdb) p *params
$2 = {freeze_min_age = -1, freeze_table_age = -1, multixact_freeze_min_age = -1, multixact_freeze_table_age = -1, 
  is_wraparound = false, log_min_duration = -1}
(gdb)

变量赋值并执行相关判断

(gdb) n
177     stmttype = (options & VACOPT_VACUUM) ? "VACUUM" : "ANALYZE";
(gdb) 
187     if (options & VACOPT_VACUUM)
(gdb) 
189         PreventInTransactionBlock(isTopLevel, stmttype);
(gdb) 
190         in_outer_xact = false;
(gdb) 
200     if (in_vacuum)
(gdb) 
209     if ((options & VACOPT_FULL) != 0 &&
(gdb)

统计信息

219     if ((options & VACOPT_VACUUM) && !IsAutoVacuumWorkerProcess())
(gdb) 
220         pgstat_vacuum_stat();
(gdb)

创建并设置内存上下文

(gdb) n
228     vac_context = AllocSetContextCreate(PortalContext,
(gdb) 
236     if (bstrategy == NULL)
(gdb) 
238         MemoryContext old_context = MemoryContextSwitchTo(vac_context);
(gdb) 
240         bstrategy = GetAccessStrategy(BAS_VACUUM);
(gdb) 
241         MemoryContextSwitchTo(old_context);
(gdb) 
243     vac_strategy = bstrategy;
(gdb) 
249     if (relations != NIL)
(gdb)

构造VacuumRelation链表

(gdb) 
251         List       *newrels = NIL;
(gdb) 
254         foreach(lc, relations)
(gdb) 
256             VacuumRelation *vrel = lfirst_node(VacuumRelation, lc);
(gdb) 
260             sublist = expand_vacuum_rel(vrel);
(gdb) p *vrel
$3 = {type = T_VacuumRelation, relation = 0x22948d0, oid = 0, va_cols = 0x0}
(gdb) p *vrel->relation
$4 = {type = T_RangeVar, catalogname = 0x0, schemaname = 0x0, relname = 0x22948b0 "t1", inh = true, 
  relpersistence = 112 'p', alias = 0x0, location = 7}
(gdb) 
(gdb) n
261             old_context = MemoryContextSwitchTo(vac_context);
(gdb) 
262             newrels = list_concat(newrels, sublist);
(gdb) 
263             MemoryContextSwitchTo(old_context);
(gdb) 
254         foreach(lc, relations)
(gdb) 
265         relations = newrels;
(gdb)

使用自主事务

284     if (options & VACOPT_VACUUM)
(gdb) 
285         use_own_xacts = true;
(gdb) 
307     if (use_own_xacts)
(gdb) 
307     if (use_own_xacts)
(gdb) 
309         Assert(!in_outer_xact);
(gdb) 
312         if (ActiveSnapshotSet())
(gdb) 
313             PopActiveSnapshot();
(gdb) 
316         CommitTransactionCommand();
(gdb) 
320     PG_TRY();
(gdb)

开始执行,设置vacuum成本计数on/off,并set/clear in_vacuum参数

(gdb) 
324         in_vacuum = true;
(gdb) 
325         VacuumCostActive = (VacuumCostDelay > 0);
(gdb) 
326         VacuumCostBalance = 0;
(gdb) 
327         VacuumPageHit = 0;
(gdb) 
328         VacuumPageMiss = 0;
(gdb) 
329         VacuumPageDirty = 0;
(gdb)

循环relation,调用vacuum_rel

334         foreach(cur, relations)
(gdb) 
336             VacuumRelation *vrel = lfirst_node(VacuumRelation, cur);
(gdb) 
338             if (options & VACOPT_VACUUM)
(gdb) 
340                 if (!vacuum_rel(vrel->oid, vrel->relation, options, params))
(gdb) 
344             if (options & VACOPT_ANALYZE)
(gdb) 
334         foreach(cur, relations)
(gdb) 
374     PG_END_TRY();
(gdb)

执行收尾工作

(gdb) 
376     in_vacuum = false;
(gdb) 
377     VacuumCostActive = false;
(gdb) 
382     if (use_own_xacts)
(gdb) 
390         StartTransactionCommand();
(gdb) 
393     if ((options & VACOPT_VACUUM) && !IsAutoVacuumWorkerProcess())
(gdb) 
399         vac_update_datfrozenxid();
(gdb) 
407     MemoryContextDelete(vac_context);
(gdb) 
408     vac_context = NULL;
(gdb)

完成调用

409 }
(gdb) 
ExecVacuum (vacstmt=0x22949c0, isTopLevel=true) at vacuum.c:142
142 }
(gdb)

到此,相信大家对“PostgreSQL中vacuum过程分析”有了更深的了解,不妨来实际操作一番吧!这里是编程网网站,更多相关内容可以进入相关频道进行查询,关注我们,继续学习!

您可能感兴趣的文档:

--结束END--

本文标题: PostgreSQL中vacuum过程分析

本文链接: https://www.lsjlt.com/news/64267.html(转载时请注明来源链接)

有问题或投稿请发送至: 邮箱/279061341@qq.com    QQ/279061341

本篇文章演示代码以及资料文档资料下载

下载Word文档到电脑,方便收藏和打印~

下载Word文档
猜你喜欢
  • PostgreSQL中vacuum过程分析
    本篇内容主要讲解“PostgreSQL中vacuum过程分析”,感兴趣的朋友不妨来看看。本文介绍的方法操作简单快捷,实用性强。下面就让小编来带大家学习“PostgreSQL中vacuum过程分析”吧!一、数...
    99+
    2024-04-02
  • PostgreSQL中vacuum过程HeapTupleSatisfiesVacuum函数分析
    本篇内容主要讲解“PostgreSQL中vacuum过程HeapTupleSatisfiesVacuum函数分析”,感兴趣的朋友不妨来看看。本文介绍的方法操作简单快捷,实用性强。下面就让小编来带大家学习“P...
    99+
    2024-04-02
  • PostgreSQL的vacuum过程中heap_vacuum_rel函数分析
    这篇文章主要介绍“PostgreSQL的vacuum过程中heap_vacuum_rel函数分析”,在日常操作中,相信很多人在PostgreSQL的vacuum过程中heap_vacuum_rel函数分析问...
    99+
    2024-04-02
  • PostgreSQL中vacuum主流程分析
    本篇内容介绍了“PostgreSQL中vacuum主流程分析”的有关知识,在实际案例的操作过程中,不少人都会遇到这样的困境,接下来就让小编带领大家学习一下如何处理这些情况吧!希望大家仔细阅读,能够学有所成!...
    99+
    2024-04-02
  • PostgreSQL中怎么监控VACUUM的处理过程
    这篇文章主要讲解了“PostgreSQL中怎么监控VACUUM的处理过程”,文中的讲解内容简单清晰,易于学习与理解,下面请大家跟着小编的思路慢慢深入,一起来研究和学习“PostgreSQL中怎么监控VACUUM的处理过程”吧!概览PG的MV...
    99+
    2023-05-31
  • PostgreSQL中如何监控VACUUM的处理过程
    这篇文章主要讲解了“PostgreSQL中如何监控VACUUM的处理过程”,文中的讲解内容简单清晰,易于学习与理解,下面请大家跟着小编的思路慢慢深入,一起来研究和学习“PostgreSQL中如何监控VACU...
    99+
    2024-04-02
  • PostgreSQL的vacuum过程中lazy_vacuum_heap函数有什么作用
    这篇文章主要介绍“PostgreSQL的vacuum过程中lazy_vacuum_heap函数有什么作用”,在日常操作中,相信很多人在PostgreSQL的vacuum过程中lazy_vacuum_heap...
    99+
    2024-04-02
  • PostgreSQL 源码解读(127)- MVCC#11(vacuum过程-vacuum_rel函数)
    本节简单介绍了PostgreSQ...
    99+
    2024-04-02
  • PostgreSQL 源码解读(135)- MVCC#19(vacuum过程-heap_execute_freeze_tuple函数)
    本节简单介绍了PostgreSQ...
    99+
    2024-04-02
  • PostgreSQL存储过程源码分析
    这篇文章主要介绍了PostgreSQL存储过程源码分析的相关知识,内容详细易懂,操作简单快捷,具有一定借鉴价值,相信大家阅读完这篇PostgreSQL存储过程源码分析文章都会有所收获,下面我们一起来看看吧。游标PL/pgSQL 游标允许我们...
    99+
    2023-07-05
  • PostgreSQL 源码解读(133)- MVCC#17(vacuum过程-lazy_vacuum_index函数#2)
    本节简单介绍了PostgreSQ...
    99+
    2024-04-02
  • 分析PostgreSQL创建函数的过程
    本篇内容主要讲解“分析PostgreSQL创建函数的过程”,感兴趣的朋友不妨来看看。本文介绍的方法操作简单快捷,实用性强。下面就让小编来带大家学习“分析PostgreSQL创建函数的过程”吧!一、数据结构F...
    99+
    2024-04-02
  • PostgreSQL中StartLogStreamer分析
    本篇内容主要讲解“PostgreSQL中StartLogStreamer分析”,感兴趣的朋友不妨来看看。本文介绍的方法操作简单快捷,实用性强。下面就让小编来带大家学习“PostgreSQL中StartLog...
    99+
    2024-04-02
  • PostgreSQL中REDO point分析
    这篇文章主要介绍“PostgreSQL中REDO point分析”,在日常操作中,相信很多人在PostgreSQL中REDO point分析问题上存在疑惑,小编查阅了各式资料,整理出简单好用的操作方法,希望...
    99+
    2024-04-02
  • 分析PostgreSQL中的tuple locks
    这篇文章主要介绍“分析PostgreSQL中的tuple locks”,在日常操作中,相信很多人在分析PostgreSQL中的tuple locks问题上存在疑惑,小编查阅了各式资料,整理出简单好用的操作方...
    99+
    2024-04-02
  • PostgreSQL中match_unsorted_outer函数分析
    这篇文章主要讲解了“PostgreSQL中match_unsorted_outer函数分析”,文中的讲解内容简单清晰,易于学习与理解,下面请大家跟着小编的思路慢慢深入,一起来研究和学习“PostgreSQL...
    99+
    2024-04-02
  • PostgreSQL中make_rel_from_joinlist函数分析
    这篇文章主要介绍“PostgreSQL中make_rel_from_joinlist函数分析”,在日常操作中,相信很多人在PostgreSQL中make_rel_from_joinlist函数分析问题上存在...
    99+
    2024-04-02
  • PostgreSQL中hash_inner_and_outer函数分析
    这篇文章主要讲解了“PostgreSQL中hash_inner_and_outer函数分析”,文中的讲解内容简单清晰,易于学习与理解,下面请大家跟着小编的思路慢慢深入,一起来研究和学习“PostgreSQL...
    99+
    2024-04-02
  • PostgreSQL中sort_inner_and_outer函数分析
    这篇文章主要讲解了“PostgreSQL中sort_inner_and_outer函数分析”,文中的讲解内容简单清晰,易于学习与理解,下面请大家跟着小编的思路慢慢深入,一起来研究和学习“PostgreSQL...
    99+
    2024-04-02
  • PostgreSQL的后台进程walsender分析
    这篇文章主要介绍“PostgreSQL的后台进程walsender分析”,在日常操作中,相信很多人在PostgreSQL的后台进程walsender分析问题上存在疑惑,小编查阅了各式资料,整理出简单好用的操...
    99+
    2024-04-02
软考高级职称资格查询
编程网,编程工程师的家园,是目前国内优秀的开源技术社区之一,形成了由开源软件库、代码分享、资讯、协作翻译、讨论区和博客等几大频道内容,为IT开发者提供了一个发现、使用、并交流开源技术的平台。
  • 官方手机版

  • 微信公众号

  • 商务合作