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

PostgreSQL中vacuum过程HeapTupleSatisfiesVacuum函数分析

2024-04-02 19:04:59 281人浏览 泡泡鱼
摘要

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

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

一、数据结构

宏定义
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;

二、源码解读

HeapTupleSatisfiesVacuum
HeapTupleSatisfiesVacuum为VACUUM操作确定元组的状态.在这里,我们主要想知道的是一个元组是否可对所有正在运行中的事务可见.如可见,则不能通过VACUUM删除该元组.

主要处理流程如下:
0.获取tuple并执行相关校验
1.条件:插入事务未提交
1.1条件:无效的xmin,该元组已废弃可删除
1.2条件:旧版本(9.0-)的判断
1.3条件:xmin为当前事务ID
1.4条件:插入事务非当前事务,正在进行中
1.5条件:xmin事务确实已提交(通过clog判断)
1.6条件:其他情况
— 至此,可以确定xmin已提交
2.条件:xmax是无效的事务ID,直接返回LIVE
3.条件:xmax只是
3.1条件:xmax事务未提交,分多事务&非多事务进行判断
3.2条件:只是锁定,返回LIVE
4.条件:存在子事务
4.1条件:xmax正在进行,返回事务进行中
4.2条件:xmax已提交,区分xmax在OldestXmin之前还是之后
4.3条件:xmax不在运行中/没有提交/没有回滚或崩溃,则设置xmax为无效事务ID
4.4默认返回LIVE
5.条件:xmax没有提交
5.1条件:删除过程中
5.2条件:通过clog判断,该事务已提交,设置事务标记位
5.3条件:其他情况,设置为无效事务ID
5.4默认返回LIVE
— 至此,可以确定xmax已提交
6.元组xmax≥OldestXmin,最近删除
7.默认元组已DEAD


HTSV_Result
HeapTupleSatisfiesVacuum(HeapTuple htup, TransactionId OldestXmin,
                         Buffer buffer)
{
    //获取tuple
    HeapTupleHeader tuple = htup->t_data;
    //校验
    Assert(ItemPointerIsValid(&htup->t_self));
    Assert(htup->t_tableOid != InvalidOid);
    
    if (!HeapTupleHeaderXminCommitted(tuple))
    {
        //1.插入事务未提交
        if (HeapTupleHeaderXminInvalid(tuple))
            //1-1.无效的xmin,该元组已废弃可删除
            return HEAPTUPLE_DEAD;
        
        //用于9.0以前版本的升级,HEAP_MOVED_OFF&HEAP_MOVED_IN已不再使用
        else if (tuple->t_infomask & HEAP_MOVED_OFF)
        {
            TransactionId xvac = HeapTupleHeaderGetXvac(tuple);
            if (TransactionIdIsCurrentTransactionId(xvac))
                return HEAPTUPLE_DELETE_IN_PROGRESS;
            if (TransactionIdIsInProgress(xvac))
                return HEAPTUPLE_DELETE_IN_PROGRESS;
            if (TransactionIdDidCommit(xvac))
            {
                SetHintBits(tuple, buffer, HEAP_XMIN_INVALID,
                            InvalidTransactionId);
                return HEAPTUPLE_DEAD;
            }
            SetHintBits(tuple, buffer, HEAP_XMIN_COMMITTED,
                        InvalidTransactionId);
        }
        
        //用于9.0以前版本的升级
        else if (tuple->t_infomask & HEAP_MOVED_IN)
        {
            TransactionId xvac = HeapTupleHeaderGetXvac(tuple);
            if (TransactionIdIsCurrentTransactionId(xvac))
                return HEAPTUPLE_INSERT_IN_PROGRESS;
            if (TransactionIdIsInProgress(xvac))
                return HEAPTUPLE_INSERT_IN_PROGRESS;
            if (TransactionIdDidCommit(xvac))
                SetHintBits(tuple, buffer, HEAP_XMIN_COMMITTED,
                            InvalidTransactionId);
            else
            {
                SetHintBits(tuple, buffer, HEAP_XMIN_INVALID,
                            InvalidTransactionId);
                return HEAPTUPLE_DEAD;
            }
        }
        else if (TransactionIdIsCurrentTransactionId(HeapTupleHeaderGetRawXmin(tuple)))
        {
            //1-3.xmin为当前事务ID
            if (tuple->t_infomask & HEAP_XMAX_INVALID)  
                //1-3-1.xmax无效,说明插入事务正在进行中
                return HEAPTUPLE_INSERT_IN_PROGRESS;
            
            //只是锁定?性能考虑,首先执行infomask-only检查
            if (HEAP_XMAX_IS_LOCKED_ONLY(tuple->t_infomask) ||
                HeapTupleHeaderIsOnlyLocked(tuple))
                //1-3-2.锁定状态(如for update之类),事务正在进行中
                return HEAPTUPLE_INSERT_IN_PROGRESS;
            
            //插入,然后删除
            if (TransactionIdIsCurrentTransactionId(HeapTupleHeaderGetUpdateXid(tuple)))
                //1-3-3.插入,然后删除
                return HEAPTUPLE_DELETE_IN_PROGRESS;
            
            //默认:插入事务正在进行中
            return HEAPTUPLE_INSERT_IN_PROGRESS;
        }
        else if (TransactionIdIsInProgress(HeapTupleHeaderGetRawXmin(tuple)))
        {
            //1-4.插入事务非当前事务,正在进行中
            
            return HEAPTUPLE_INSERT_IN_PROGRESS;
        }
        else if (TransactionIdDidCommit(HeapTupleHeaderGetRawXmin(tuple)))
            //1-5.xmin事务确实已提交(通过clog判断)
            SetHintBits(tuple, buffer, HEAP_XMIN_COMMITTED,
                        HeapTupleHeaderGetRawXmin(tuple));
        else
        {
            //1-5.其他情况
            //既不在进行中,也没有提交,要么是回滚,要么是崩溃了
            
            //设置标记位
            SetHintBits(tuple, buffer, HEAP_XMIN_INVALID,
                        InvalidTransactionId);
            //返回废弃标记
            return HEAPTUPLE_DEAD;
        }
        
    }
    
    if (tuple->t_infomask & HEAP_XMAX_INVALID)
        //------- 2.xmax是无效的事务ID,直接返回LIVE
        return HEAPTUPLE_LIVE;
    if (HEAP_XMAX_IS_LOCKED_ONLY(tuple->t_infomask))
    {
        //------- 3.锁定
        
        if (!(tuple->t_infomask & HEAP_XMAX_COMMITTED))
        {
            //3.1 xmax事务未提交
            if (tuple->t_infomask & HEAP_XMAX_IS_MULTI)
            {
                //3.1.1 多事务
                
                if (!HEAP_LOCKED_UPGRADED(tuple->t_infomask) &&
                    MultiXactIdIsRunning(HeapTupleHeaderGetRawXmax(tuple),
                                         true))
                    return HEAPTUPLE_LIVE;
                //其他情况,根据clog重新设置事务状态标记位
                SetHintBits(tuple, buffer, HEAP_XMAX_INVALID, InvalidTransactionId);
            }
            else
            {
                //3.1.2 非多事务
                if (TransactionIdIsInProgress(HeapTupleHeaderGetRawXmax(tuple)))
                    //xmax事务正在进行,返回LIVE
                    return HEAPTUPLE_LIVE;
                //否则,根据clog重新设置事务状态标记位
                SetHintBits(tuple, buffer, HEAP_XMAX_INVALID,
                            InvalidTransactionId);
            }
        }
        
        //3.2 只是锁定,返回LIVE
        return HEAPTUPLE_LIVE;
    }
    if (tuple->t_infomask & HEAP_XMAX_IS_MULTI)
    {
        //4.存在子事务
        //获取删除事务号xmax
        TransactionId xmax = HeapTupleGetUpdateXid(tuple);
        
        Assert(!HEAP_XMAX_IS_LOCKED_ONLY(tuple->t_infomask));
        
        //根据上述xmax的判断,到这里可以肯定xmax是有效的
        Assert(TransactionIdIsValid(xmax));
        if (TransactionIdIsInProgress(xmax))
            //4.1 xmax正在进行,返回进行中
            return HEAPTUPLE_DELETE_IN_PROGRESS;
        else if (TransactionIdDidCommit(xmax))
        {
            //4.2 xmax已提交
            
            if (!TransactionIdPrecedes(xmax, OldestXmin))
                //4.2.1 xmax在OldestXmin之后,
                //表示在OldestXmin之后才删除,返回HEAPTUPLE_RECENTLY_DEAD
                return HEAPTUPLE_RECENTLY_DEAD;
            //4.2.2 xmax在OldestXmin之前,返回DEAD
            return HEAPTUPLE_DEAD;
        }
        else if (!MultiXactIdIsRunning(HeapTupleHeaderGetRawXmax(tuple), false))
        {
            
            //4.3 xmax不在运行中/没有提交/没有回滚或崩溃,则设置xmax为无效事务ID
            SetHintBits(tuple, buffer, HEAP_XMAX_INVALID, InvalidTransactionId);
        }
        //4.4 默认返回LIVE
        return HEAPTUPLE_LIVE;
    }
    if (!(tuple->t_infomask & HEAP_XMAX_COMMITTED))
    {
        //5.xmax没有提交
        if (TransactionIdIsInProgress(HeapTupleHeaderGetRawXmax(tuple)))
            //5.1 删除过程中
            return HEAPTUPLE_DELETE_IN_PROGRESS;
        else if (TransactionIdDidCommit(HeapTupleHeaderGetRawXmax(tuple)))
            //5.2 通过clog判断,该事务已提交,设置事务标记位
            SetHintBits(tuple, buffer, HEAP_XMAX_COMMITTED,
                        HeapTupleHeaderGetRawXmax(tuple));
        else
        {
            
            //5.3 其他情况,设置为无效事务ID
            SetHintBits(tuple, buffer, HEAP_XMAX_INVALID,
                        InvalidTransactionId);
            //返回LIVE
            return HEAPTUPLE_LIVE;
        }
        
        //至此,xmax可以确认已提交
    }
    
    if (!TransactionIdPrecedes(HeapTupleHeaderGetRawXmax(tuple), OldestXmin))
        //6.元组xmax≥OldestXmin,最近删除
        return HEAPTUPLE_RECENTLY_DEAD;
    
    //7. 默认元组已DEAD
    return HEAPTUPLE_DEAD;
}

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

您可能感兴趣的文档:

--结束END--

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

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

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

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

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

下载Word文档
猜你喜欢
  • oracle怎么查询当前用户所有的表
    要查询当前用户拥有的所有表,可以使用以下 sql 命令:select * from user_tables; 如何查询当前用户拥有的所有表 要查询当前用户拥有的所有表,可以使...
    99+
    2024-05-15
    oracle
  • oracle怎么备份表中数据
    oracle 表数据备份的方法包括:导出数据 (exp):将表数据导出到外部文件。导入数据 (imp):将导出文件中的数据导入表中。用户管理的备份 (umr):允许用户控制备份和恢复过程...
    99+
    2024-05-15
    oracle
  • oracle怎么做到数据实时备份
    oracle 实时备份通过持续保持数据库和事务日志的副本来实现数据保护,提供快速恢复。实现机制主要包括归档重做日志和 asm 卷管理系统。它最小化数据丢失、加快恢复时间、消除手动备份任务...
    99+
    2024-05-15
    oracle 数据丢失
  • oracle怎么查询所有的表空间
    要查询 oracle 中的所有表空间,可以使用 sql 语句 "select tablespace_name from dba_tablespaces",其中 dba_tabl...
    99+
    2024-05-15
    oracle
  • oracle怎么创建新用户并赋予权限设置
    答案:要创建 oracle 新用户,请执行以下步骤:以具有 create user 权限的用户身份登录;在 sql*plus 窗口中输入 create user identified ...
    99+
    2024-05-15
    oracle
  • oracle怎么建立新用户
    在 oracle 数据库中创建用户的方法:使用 sql*plus 连接数据库;使用 create user 语法创建新用户;根据用户需要授予权限;注销并重新登录以使更改生效。 如何在 ...
    99+
    2024-05-15
    oracle
  • oracle怎么创建新用户并赋予权限密码
    本教程详细介绍了如何使用 oracle 创建一个新用户并授予其权限:创建新用户并设置密码。授予对特定表的读写权限。授予创建序列的权限。根据需要授予其他权限。 如何使用 Oracle 创...
    99+
    2024-05-15
    oracle
  • oracle怎么查询时间段内的数据记录表
    在 oracle 数据库中查询指定时间段内的数据记录表,可以使用 between 操作符,用于比较日期或时间的范围。语法:select * from table_name wh...
    99+
    2024-05-15
    oracle
  • oracle怎么查看表的分区
    问题:如何查看 oracle 表的分区?步骤:查询数据字典视图 all_tab_partitions,指定表名。结果显示分区名称、上边界值和下边界值。 如何查看 Oracle 表的分区...
    99+
    2024-05-15
    oracle
  • oracle怎么导入dump文件
    要导入 dump 文件,请先停止 oracle 服务,然后使用 impdp 命令。步骤包括:停止 oracle 数据库服务。导航到 oracle 数据泵工具目录。使用 impdp 命令导...
    99+
    2024-05-15
    oracle
软考高级职称资格查询
编程网,编程工程师的家园,是目前国内优秀的开源技术社区之一,形成了由开源软件库、代码分享、资讯、协作翻译、讨论区和博客等几大频道内容,为IT开发者提供了一个发现、使用、并交流开源技术的平台。
  • 官方手机版

  • 微信公众号

  • 商务合作