最近2018中文字幕在日韩欧美国产成人片_国产日韩精品一区二区在线_在线观看成年美女黄网色视频_国产精品一区三区五区_国产精彩刺激乱对白_看黄色黄大色黄片免费_人人超碰自拍cao_国产高清av在线_亚洲精品电影av_日韩美女尤物视频网站

RELATEED CONSULTING
相關(guān)咨詢
選擇下列產(chǎn)品馬上在線溝通
服務(wù)時間:8:30-17:00
你可能遇到了下面的問題
關(guān)閉右側(cè)工具欄

新聞中心

這里有您想知道的互聯(lián)網(wǎng)營銷解決方案
PostgreSQL中vacuum過程HeapTupleSatisfiesVacuum函數(shù)分析

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

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

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

宏定義
Vacuum和Analyze命令選項

/* ----------------------
 *      Vacuum and Analyze Statements
 *      Vacuum和Analyze命令選項
 * 
 * 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.
 * 雖然在這里有兩種不同的語句,但只需要使用統(tǒng)一的Node類型即可.
 * 注意至少VACOPT_VACUUM/VACOPT_ANALYZE在選項中設(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).在這里,我們主要想知道的是一個元組是否可對所有正在運行中的事務(wù)可見.如可見,則不能通過VACUUM刪除該元組.

主要處理流程如下:
0.獲取tuple并執(zhí)行相關(guān)校驗
1.條件:插入事務(wù)未提交
1.1條件:無效的xmin,該元組已廢棄可刪除
1.2條件:舊版本(9.0-)的判斷
1.3條件:xmin為當(dāng)前事務(wù)ID
1.4條件:插入事務(wù)非當(dāng)前事務(wù),正在進行中
1.5條件:xmin事務(wù)確實已提交(通過clog判斷)
1.6條件:其他情況
— 至此,可以確定xmin已提交
2.條件:xmax是無效的事務(wù)ID,直接返回LIVE
3.條件:xmax只是鎖定
3.1條件:xmax事務(wù)未提交,分多事務(wù)&非多事務(wù)進行判斷
3.2條件:只是鎖定,返回LIVE
4.條件:存在子事務(wù)
4.1條件:xmax正在進行,返回事務(wù)進行中
4.2條件:xmax已提交,區(qū)分xmax在OldestXmin之前還是之后
4.3條件:xmax不在運行中/沒有提交/沒有回滾或崩潰,則設(shè)置xmax為無效事務(wù)ID
4.4默認返回LIVE
5.條件:xmax沒有提交
5.1條件:刪除過程中
5.2條件:通過clog判斷,該事務(wù)已提交,設(shè)置事務(wù)標(biāo)記位
5.3條件:其他情況,設(shè)置為無效事務(wù)ID
5.4默認返回LIVE
— 至此,可以確定xmax已提交
6.元組xmax≥OldestXmin,最近刪除
7.默認元組已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).
 *  在這里,我們主要想知道的是一個元組是否可對所有正在運行中的事務(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是一個cutoff XID(通過GetOldestXmin函數(shù)獲得).
 * 通過XIDs >= OldestXmin刪除的元組被視為"最近死亡",它們可能仍然對某些正在進行中的事務(wù)可見,
 *   因此就算刪除事務(wù)已提交,我們?nèi)匀徊荒芮宄鼈?
 */
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);
    /*
     * 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ù)已回滾,元組對其他事務(wù)均不可見,因此可以馬上刪除.
     */
    if (!HeapTupleHeaderXminCommitted(tuple))
    {
        //1.插入事務(wù)未提交
        if (HeapTupleHeaderXminInvalid(tuple))
            //1-1.無效的xmin,該元組已廢棄可刪除
            return HEAPTUPLE_DEAD;
        /* Used by pre-9.0 binary upgrades */
        //用于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);
        }
        /* Used by pre-9.0 binary upgrades */
        //用于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為當(dāng)前事務(wù)ID
            if (tuple->t_infomask & HEAP_XMAX_INVALID)  /* xid invalid */
                //1-3-1.xmax無效,說明插入事務(wù)正在進行中
                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ù)正在進行中
                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 */
            //默認:插入事務(wù)正在進行中
            return HEAPTUPLE_INSERT_IN_PROGRESS;
        }
        else if (TransactionIdIsInProgress(HeapTupleHeaderGetRawXmin(tuple)))
        {
            //1-4.插入事務(wù)非當(dāng)前事務(wù),正在進行中
            /*
             * 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ū)分正在進行的插入/刪除操作 - 但這對于大多數(shù)調(diào)用者并沒有好處,甚至有害
             * 我們寧愿讓調(diào)用者查看/等待xmin而不是xmax。
             * 返回INSERT_IN_PROGRESS總是正確的,因為這是從其他后臺進程視圖中看到正在發(fā)生的。
             */
            return HEAPTUPLE_INSERT_IN_PROGRESS;
        }
        else if (TransactionIdDidCommit(HeapTupleHeaderGetRawXmin(tuple)))
            //1-5.xmin事務(wù)確實已提交(通過clog判斷)
            SetHintBits(tuple, buffer, HEAP_XMIN_COMMITTED,
                        HeapTupleHeaderGetRawXmin(tuple));
        else
        {
            //1-5.其他情況
            //既不在進行中,也沒有提交,要么是回滾,要么是崩潰了
            /*
             * 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.
         * 在這個點上,xmin事務(wù)確認已提交,但這時候還是不能設(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ù)確實只是鎖定該元組,因此該元組是存活狀態(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ù)不可能運行,否則的話,只能執(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ù)正在進行,返回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.
         * 我們確實不需要真正關(guān)心xmax是否提交/回滾/崩潰.
         * 我們知道xmax事務(wù)鎖定了元組,但沒有而且"從未"更新過該元組.
         */
        //3.2 只是鎖定,返回LIVE
        return HEAPTUPLE_LIVE;
    }
    if (tuple->t_infomask & HEAP_XMAX_IS_MULTI)
    {
        //4.存在子事務(wù)
        //獲取刪除事務(wù)號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正在進行,返回進行中
            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不在運行中/沒有提交/沒有回滾或崩潰,則設(shè)置xmax為無效事務(wù)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判斷,該事務(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可以確認已提交
    }
    /*
     * 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. 默認元組已DEAD
    return HEAPTUPLE_DEAD;
}

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


新聞標(biāo)題:PostgreSQL中vacuum過程HeapTupleSatisfiesVacuum函數(shù)分析
網(wǎng)站路徑:http://fisionsoft.com.cn/article/piocig.html