本篇內(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)站制作公司
宏定義
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)