PostgreSQL中vacuum過程HeapTupleSatisfiesVacuum函數(shù)分析

本篇內(nèi)容主要講解“PostgreSQL中vacuum過程HeapTupleSatisfiesVacuum函數(shù)分析”,感興趣的朋友不妨來看看。本文介紹的方法操作簡(jiǎn)單快捷,實(shí)用性強(qiáng)。下面就讓小編來帶大家學(xué)習(xí)“PostgreSQL中vacuum過程HeapTupleSatisfiesVacuum函數(shù)分析”吧!

我們提供的服務(wù)有:做網(wǎng)站、成都網(wǎng)站建設(shè)、微信公眾號(hào)開發(fā)、網(wǎng)站優(yōu)化、網(wǎng)站認(rèn)證、黑龍江ssl等。為近1000家企事業(yè)單位解決了網(wǎng)站和推廣的問題。提供周到的售前咨詢和貼心的售后服務(wù),是有科學(xué)管理、有技術(shù)的黑龍江網(wǎng)站制作公司

一、數(shù)據(jù)結(jié)構(gòu)

宏定義
Vacuum和Analyze命令選項(xiàng)

/* ----------------------
 *      Vacuum and Analyze Statements
 *      Vacuum和Analyze命令選項(xiàng)
 * 
 * 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.
 * 雖然在這里有兩種不同的語(yǔ)句,但只需要使用統(tǒng)一的Node類型即可.
 * 注意至少VACOPT_VACUUM/VACOPT_ANALYZE在選項(xiàng)中設(shè)置.
 * ----------------------
 */
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;

二、源碼解讀

HeapTupleSatisfiesVacuum
HeapTupleSatisfiesVacuum為VACUUM操作確定元組的狀態(tài).在這里,我們主要想知道的是一個(gè)元組是否可對(duì)所有正在運(yùn)行中的事務(wù)可見.如可見,則不能通過VACUUM刪除該元組.

主要處理流程如下:
0.獲取tuple并執(zhí)行相關(guān)校驗(yàn)
1.條件:插入事務(wù)未提交
1.1條件:無效的xmin,該元組已廢棄可刪除
1.2條件:舊版本(9.0-)的判斷
1.3條件:xmin為當(dāng)前事務(wù)ID
1.4條件:插入事務(wù)非當(dāng)前事務(wù),正在進(jìn)行中
1.5條件:xmin事務(wù)確實(shí)已提交(通過clog判斷)
1.6條件:其他情況
— 至此,可以確定xmin已提交
2.條件:xmax是無效的事務(wù)ID,直接返回LIVE
3.條件:xmax只是鎖定
3.1條件:xmax事務(wù)未提交,分多事務(wù)&非多事務(wù)進(jìn)行判斷
3.2條件:只是鎖定,返回LIVE
4.條件:存在子事務(wù)
4.1條件:xmax正在進(jìn)行,返回事務(wù)進(jìn)行中
4.2條件:xmax已提交,區(qū)分xmax在OldestXmin之前還是之后
4.3條件:xmax不在運(yùn)行中/沒有提交/沒有回滾或崩潰,則設(shè)置xmax為無效事務(wù)ID
4.4默認(rèn)返回LIVE
5.條件:xmax沒有提交
5.1條件:刪除過程中
5.2條件:通過clog判斷,該事務(wù)已提交,設(shè)置事務(wù)標(biāo)記位
5.3條件:其他情況,設(shè)置為無效事務(wù)ID
5.4默認(rèn)返回LIVE
— 至此,可以確定xmax已提交
6.元組xmax≥OldestXmin,最近刪除
7.默認(rèn)元組已DEAD

/*
 * HeapTupleSatisfiesVacuum
 *
 *  Determine the status of tuples for VACUUM purposes.  Here, what
 *  we mainly want to know is if a tuple is potentially visible to *any*
 *  running transaction.  If so, it can't be removed yet by VACUUM.
 *  為VACUUM確定元組的狀態(tài).
 *  在這里,我們主要想知道的是一個(gè)元組是否可對(duì)所有正在運(yùn)行中的事務(wù)可見.
 *  如可見,則不能通過VACUUM刪除該元組.
 *
 * OldestXmin is a cutoff XID (obtained from GetOldestXmin()).  Tuples
 * deleted by XIDs >= OldestXmin are deemed "recently dead"; they might
 * still be visible to some open transaction, so we can't remove them,
 * even if we see that the deleting transaction has committed.
 * OldestXmin是一個(gè)cutoff XID(通過GetOldestXmin函數(shù)獲得).
 * 通過XIDs >= OldestXmin刪除的元組被視為"最近死亡",它們可能仍然對(duì)某些正在進(jìn)行中的事務(wù)可見,
 *   因此就算刪除事務(wù)已提交,我們?nèi)匀徊荒芮宄鼈?
 */
HTSV_Result
HeapTupleSatisfiesVacuum(HeapTuple htup, TransactionId OldestXmin,
                         Buffer buffer)
{
    //獲取tuple
    HeapTupleHeader tuple = htup->t_data;
    //校驗(yàn)
    Assert(ItemPointerIsValid(&htup->t_self));
    Assert(htup->t_tableOid != InvalidOid);
    /*
     * Has inserting transaction committed?
     * 插入事務(wù)已提交?
     *
     * If the inserting transaction aborted, then the tuple was never visible
     * to any other transaction, so we can delete it immediately.
     * 如果插入事務(wù)已回滾,元組對(duì)其他事務(wù)均不可見,因此可以馬上刪除.
     */
    if (!HeapTupleHeaderXminCommitted(tuple))
    {
        //1.插入事務(wù)未提交
        if (HeapTupleHeaderXminInvalid(tuple))
            //1-1.無效的xmin,該元組已廢棄可刪除
            return HEAPTUPLE_DEAD;
        /* Used by pre-9.0 binary upgrades */
        //用于9.0以前版本的升級(jí),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);
        }
        /* Used by pre-9.0 binary upgrades */
        //用于9.0以前版本的升級(jí)
        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為當(dāng)前事務(wù)ID
            if (tuple->t_infomask & HEAP_XMAX_INVALID)  /* xid invalid */
                //1-3-1.xmax無效,說明插入事務(wù)正在進(jìn)行中
                return HEAPTUPLE_INSERT_IN_PROGRESS;
            /* only locked? run infomask-only check first, for performance */
            //只是鎖定?性能考慮,首先執(zhí)行infomask-only檢查
            if (HEAP_XMAX_IS_LOCKED_ONLY(tuple->t_infomask) ||
                HeapTupleHeaderIsOnlyLocked(tuple))
                //1-3-2.鎖定狀態(tài)(如for update之類),事務(wù)正在進(jìn)行中
                return HEAPTUPLE_INSERT_IN_PROGRESS;
            /* inserted and then deleted by same xact */
            //插入,然后刪除
            if (TransactionIdIsCurrentTransactionId(HeapTupleHeaderGetUpdateXid(tuple)))
                //1-3-3.插入,然后刪除
                return HEAPTUPLE_DELETE_IN_PROGRESS;
            /* deleting subtransaction must have aborted */
            //默認(rèn):插入事務(wù)正在進(jìn)行中
            return HEAPTUPLE_INSERT_IN_PROGRESS;
        }
        else if (TransactionIdIsInProgress(HeapTupleHeaderGetRawXmin(tuple)))
        {
            //1-4.插入事務(wù)非當(dāng)前事務(wù),正在進(jìn)行中
            /*
             * It'd be possible to discern between INSERT/DELETE in progress
             * here by looking at xmax - but that doesn't seem beneficial for
             * the majority of callers and even detrimental for some. We'd
             * rather have callers look at/wait for xmin than xmax. It's
             * always correct to return INSERT_IN_PROGRESS because that's
             * what's happening from the view of other backends.
             * 通過查看xmax,可以區(qū)分正在進(jìn)行的插入/刪除操作 - 但這對(duì)于大多數(shù)調(diào)用者并沒有好處,甚至有害
             * 我們寧愿讓調(diào)用者查看/等待xmin而不是xmax。
             * 返回INSERT_IN_PROGRESS總是正確的,因?yàn)檫@是從其他后臺(tái)進(jìn)程視圖中看到正在發(fā)生的。
             */
            return HEAPTUPLE_INSERT_IN_PROGRESS;
        }
        else if (TransactionIdDidCommit(HeapTupleHeaderGetRawXmin(tuple)))
            //1-5.xmin事務(wù)確實(shí)已提交(通過clog判斷)
            SetHintBits(tuple, buffer, HEAP_XMIN_COMMITTED,
                        HeapTupleHeaderGetRawXmin(tuple));
        else
        {
            //1-5.其他情況
            //既不在進(jìn)行中,也沒有提交,要么是回滾,要么是崩潰了
            /*
             * Not in Progress, Not Committed, so either Aborted or crashed
             */
            //設(shè)置標(biāo)記位
            SetHintBits(tuple, buffer, HEAP_XMIN_INVALID,
                        InvalidTransactionId);
            //返回廢棄標(biāo)記
            return HEAPTUPLE_DEAD;
        }
        /*
         * At this point the xmin is known committed, but we might not have
         * been able to set the hint bit yet; so we can no longer Assert that
         * it's set.
         * 在這個(gè)點(diǎn)上,xmin事務(wù)確認(rèn)已提交,但這時(shí)候還是不能設(shè)置hint bit,
         *   因此不能斷定已設(shè)置標(biāo)記.
         */
    }
    /*
     * Okay, the inserter committed, so it was good at some point.  Now what
     * about the deleting transaction?
     * 插入數(shù)據(jù)的事務(wù)已提交,現(xiàn)在可以看看刪除事務(wù)的狀態(tài)了.
     */
    if (tuple->t_infomask & HEAP_XMAX_INVALID)
        //------- 2.xmax是無效的事務(wù)ID,直接返回LIVE
        return HEAPTUPLE_LIVE;
    if (HEAP_XMAX_IS_LOCKED_ONLY(tuple->t_infomask))
    {
        //------- 3.鎖定
        /*
         * "Deleting" xact really only locked it, so the tuple is live in any
         * case.  However, we should make sure that either XMAX_COMMITTED or
         * XMAX_INVALID gets set once the xact is gone, to reduce the costs of
         * examining the tuple for future xacts.
         * "Deleting"事務(wù)確實(shí)只是鎖定該元組,因此該元組是存活狀態(tài).
         * 但是,我們應(yīng)該確保不管是XMAX_COMMITTED還是XMAX_INVALID標(biāo)記,應(yīng)該在事務(wù)完結(jié)后馬上設(shè)置,
         *   這樣可以減少為了事務(wù)檢查元組狀態(tài)的成本.
         */
        if (!(tuple->t_infomask & HEAP_XMAX_COMMITTED))
        {
            //3.1 xmax事務(wù)未提交
            if (tuple->t_infomask & HEAP_XMAX_IS_MULTI)
            {
                //3.1.1 多事務(wù)
                /*
                 * If it's a pre-pg_upgrade tuple, the multixact cannot
                 * possibly be running; otherwise have to check.
                 * 如果是pre-pg_upgrade元組,多事務(wù)不可能運(yùn)行,否則的話,只能執(zhí)行檢查
                 */
                if (!HEAP_LOCKED_UPGRADED(tuple->t_infomask) &&
                    MultiXactIdIsRunning(HeapTupleHeaderGetRawXmax(tuple),
                                         true))
                    return HEAPTUPLE_LIVE;
                //其他情況,根據(jù)clog重新設(shè)置事務(wù)狀態(tài)標(biāo)記位
                SetHintBits(tuple, buffer, HEAP_XMAX_INVALID, InvalidTransactionId);
            }
            else
            {
                //3.1.2 非多事務(wù)
                if (TransactionIdIsInProgress(HeapTupleHeaderGetRawXmax(tuple)))
                    //xmax事務(wù)正在進(jìn)行,返回LIVE
                    return HEAPTUPLE_LIVE;
                //否則,根據(jù)clog重新設(shè)置事務(wù)狀態(tài)標(biāo)記位
                SetHintBits(tuple, buffer, HEAP_XMAX_INVALID,
                            InvalidTransactionId);
            }
        }
        /*
         * We don't really care whether xmax did commit, abort or crash. We
         * know that xmax did lock the tuple, but it did not and will never
         * actually update it.
         * 我們確實(shí)不需要真正關(guān)心xmax是否提交/回滾/崩潰.
         * 我們知道xmax事務(wù)鎖定了元組,但沒有而且"從未"更新過該元組.
         */
        //3.2 只是鎖定,返回LIVE
        return HEAPTUPLE_LIVE;
    }
    if (tuple->t_infomask & HEAP_XMAX_IS_MULTI)
    {
        //4.存在子事務(wù)
        //獲取刪除事務(wù)號(hào)xmax
        TransactionId xmax = HeapTupleGetUpdateXid(tuple);
        /* already checked above */
        Assert(!HEAP_XMAX_IS_LOCKED_ONLY(tuple->t_infomask));
        /* not LOCKED_ONLY, so it has to have an xmax */
        //根據(jù)上述xmax的判斷,到這里可以肯定xmax是有效的
        Assert(TransactionIdIsValid(xmax));
        if (TransactionIdIsInProgress(xmax))
            //4.1 xmax正在進(jìn)行,返回進(jìn)行中
            return HEAPTUPLE_DELETE_IN_PROGRESS;
        else if (TransactionIdDidCommit(xmax))
        {
            //4.2 xmax已提交
            /*
             * The multixact might still be running due to lockers.  If the
             * updater is below the xid horizon, we have to return DEAD
             * regardless -- otherwise we could end up with a tuple where the
             * updater has to be removed due to the horizon, but is not pruned
             * away.  It's not a problem to prune that tuple, because any
             * remaining lockers will also be present in newer tuple versions.
             */
            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))
        {
            /*
             * Not in Progress, Not Committed, so either Aborted or crashed.
             * Mark the Xmax as invalid.
             */
            //4.3 xmax不在運(yùn)行中/沒有提交/沒有回滾或崩潰,則設(shè)置xmax為無效事務(wù)ID
            SetHintBits(tuple, buffer, HEAP_XMAX_INVALID, InvalidTransactionId);
        }
        //4.4 默認(rèn)返回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判斷,該事務(wù)已提交,設(shè)置事務(wù)標(biāo)記位
            SetHintBits(tuple, buffer, HEAP_XMAX_COMMITTED,
                        HeapTupleHeaderGetRawXmax(tuple));
        else
        {
            /*
             * Not in Progress, Not Committed, so either Aborted or crashed
             */
            //5.3 其他情況,設(shè)置為無效事務(wù)ID
            SetHintBits(tuple, buffer, HEAP_XMAX_INVALID,
                        InvalidTransactionId);
            //返回LIVE
            return HEAPTUPLE_LIVE;
        }
        /*
         * At this point the xmax is known committed, but we might not have
         * been able to set the hint bit yet; so we can no longer Assert that
         * it's set.
         */
        //至此,xmax可以確認(rèn)已提交
    }
    /*
     * Deleter committed, but perhaps it was recent enough that some open
     * transactions could still see the tuple.
     */
    if (!TransactionIdPrecedes(HeapTupleHeaderGetRawXmax(tuple), OldestXmin))
        //6.元組xmax≥OldestXmin,最近刪除
        return HEAPTUPLE_RECENTLY_DEAD;
    /* Otherwise, it's dead and removable */
    //7. 默認(rèn)元組已DEAD
    return HEAPTUPLE_DEAD;
}

到此,相信大家對(duì)“PostgreSQL中vacuum過程HeapTupleSatisfiesVacuum函數(shù)分析”有了更深的了解,不妨來實(shí)際操作一番吧!這里是創(chuàng)新互聯(lián)網(wǎng)站,更多相關(guān)內(nèi)容可以進(jìn)入相關(guān)頻道進(jìn)行查詢,關(guān)注我們,繼續(xù)學(xué)習(xí)!

分享文章:PostgreSQL中vacuum過程HeapTupleSatisfiesVacuum函數(shù)分析
文章分享:http://muchs.cn/article6/piocig.html

成都網(wǎng)站建設(shè)公司_創(chuàng)新互聯(lián),為您提供小程序開發(fā)、網(wǎng)站改版、網(wǎng)站維護(hù)、網(wǎng)站建設(shè)、App開發(fā)手機(jī)網(wǎng)站建設(shè)

廣告

聲明:本網(wǎng)站發(fā)布的內(nèi)容(圖片、視頻和文字)以用戶投稿、用戶轉(zhuǎn)載內(nèi)容為主,如果涉及侵權(quán)請(qǐng)盡快告知,我們將會(huì)在第一時(shí)間刪除。文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如需處理請(qǐng)聯(lián)系客服。電話:028-86922220;郵箱:631063699@qq.com。內(nèi)容未經(jīng)允許不得轉(zhuǎn)載,或轉(zhuǎn)載時(shí)需注明來源: 創(chuàng)新互聯(lián)

外貿(mào)網(wǎng)站制作