IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> 大数据 -> PostgreSQL思考---元组何时可以被删除? -> 正文阅读

[大数据]PostgreSQL思考---元组何时可以被删除?

PostgreSQL思考—元组何时可以被删除?

预备知识

PostgreSQL 事务—MVCC

概述

PostgreSQL支持了MVCC,所以当执行Delete时,不会也不能彻底删除相关元组。对于Delete操作所涉及的元组,PostgreSQL只是设置其t_xmax来表示元组已经被t_xmax对应的事务删除。但此时,这条元组可能依然对某些查询事务可见,这就是元组不能直接删除的原因。那么接下来就涉及两个问题?

  • 元组何时可以被删除?
  • 元组何时被删除?

关于元组何时被删除,这里直接给出答案:在用户执行Vacuum时。而元组何时可以被删除则是本文重点讨论的内容。其实这个问题的核心思想很简单,回到元组不能被直接删除,是因为该元组还可能对其他事务可见。那么,只有当元组对所有事务都不可见时,元组才可以被真正删除!在《PostgreSQL 事务—MVCC》中,我们讨论过事务可见性元组可见性,所以我们知道,删除的元组对所有事务都不可见,就意味着元组的t_xmax对所有事务都可见!

这个核心思想,说着比较简单,但是做起来却比较难,下面我们来详细阐述如何判断元组是否可以删除。

元组过期

从前面的描述中,我们知道,一条元组可以被真正删除需要具备两点要素:

  • t_xmax不为0
  • t_xmax被所有活跃事务可见

那么判断一条元组是否可以被删除其实只需要在全局事务链中判断t_xmax的可见性即可。通过《PostgreSQL 事务—MVCC》我们不难看出,判断可见性是一个比较复杂的流程,所以如果按照可见性判断的流程来确定元组是否可以被删除,效率将十分低下。那么有没有什么办法可以提高效率呢?当然有。

在PostgreSQL中,存在一个全局的PGXACT数组,数组中的每一个PGXACT元组代表一个当前的用户进程。PostgreSQL在执行增、删、查、改之前都需要对当前的活跃事务链做一个快照(Snapshot)。然后将快照中最小的事务id存放在PGXACT的xmin成员中。通过《PostgreSQL 事务—MVCC》我们知道,对于当前事务而言,事务id小于xmin的事务对当前事务都可见。那么,如果我们遍历PGXACT数组,获取所有PGXACT->xmin中最小的一个xmin作为globalxmin。事务id小于globalxmin的事务即对当前所有的事务均可见

所以如果我们在每次增、删、查、改之前获取并修改globalxmin,当我们需要判断元组是否可以被删除时,只需要判断元组的t_xmax是否小于globalxmin即可。

获取globalxmin的代码如下:

//procarray.c line 1585
numProcs = arrayP->numProcs;
for (index = 0; index < numProcs; index++)
{
    int			pgprocno = pgprocnos[index];
    volatile PGXACT *pgxact = &allPgXact[pgprocno];
    TransactionId xid;
    
    if (pgxact->vacuumFlags & PROC_IN_LOGICAL_DECODING)
        continue;

    /* Ignore procs running LAZY VACUUM */
    if (pgxact->vacuumFlags & PROC_IN_VACUUM)
        continue;

    /* Update globalxmin to be the smallest valid xmin */
    xid = pgxact->xmin; /* fetch just once */
    if (TransactionIdIsNormal(xid) &&
        NormalTransactionIdPrecedes(xid, globalxmin))
        globalxmin = xid;

    /* Fetch xid just once - see GetNewTransactionId */
    xid = pgxact->xid;

    if (!TransactionIdIsNormal(xid)
        || !NormalTransactionIdPrecedes(xid, xmax))
        continue;

    if (NormalTransactionIdPrecedes(xid, xmin))
        xmin = xid;
    if (pgxact == MyPgXact)
        continue;

    /* Add XID to snapshot. */
    snapshot->xip[count++] = xid;

    if (!suboverflowed)
    {
        if (pgxact->overflowed)
            suboverflowed = true;
        else
        {
            int	nxids = pgxact->nxids;

            if (nxids > 0)
            {
                volatile PGPROC *proc = &allProcs[pgprocno];

                memcpy(snapshot->subxip + subcount,
                       (void *) proc->subxids.xids,
                       nxids * sizeof(TransactionId));
                subcount += nxids;
            }
        }
    }
}

判断元组是否可以被删除的函数为HeapTupleSatisfiesVacuum

  大数据 最新文章
实现Kafka至少消费一次
亚马逊云科技:还在苦于ETL?Zero ETL的时代
初探MapReduce
【SpringBoot框架篇】32.基于注解+redis实现
Elasticsearch:如何减少 Elasticsearch 集
Go redis操作
Redis面试题
专题五 Redis高并发场景
基于GBase8s和Calcite的多数据源查询
Redis——底层数据结构原理
上一篇文章      下一篇文章      查看所有文章
加:2021-11-11 12:46:40  更:2021-11-11 12:47:39 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/24 6:06:41-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码