日韩久久久精品,亚洲精品久久久久久久久久久,亚洲欧美一区二区三区国产精品 ,一区二区福利

PostgreSQL啟動過程中的那些事十六:啟動進程三

系統(tǒng) 3988 0

話說啟動進程調(diào)用StartupXLOG啟動xlog,根據(jù)情況,如果需要就排除系統(tǒng)故障引起的數(shù)據(jù)庫不一致狀態(tài),做相應(yīng)的REDO或UNDO,然后創(chuàng)建一個檢查點,把所有共享內(nèi)存磁盤緩沖和提交數(shù)據(jù)緩沖寫并文件同步到磁盤、把檢查點插入xlog文件、更新控制文件,使數(shù)據(jù)庫達到一種狀態(tài) 。

這節(jié)接著討論啟動進程在創(chuàng)建檢查點時調(diào)用的 CheckPointGuts 方法(在創(chuàng)建重啟點時也會調(diào)用這個方法)。 CheckPointGuts 方法功能是刷出所有共享內(nèi)存中的數(shù)據(jù)到磁盤并做文件同步,共享內(nèi)存中的數(shù)據(jù)包括 clog 、 subtrans 、 multixact predicate 、 relationmap buffer (數(shù)據(jù)文件)和 twophase 相關(guān)數(shù)據(jù)。 CheckPointGuts 方法定義和“ CheckPointGuts 方法調(diào)用序列圖 ”見下面。

static void

CheckPointGuts(XLogRecPtrcheckPointRedo, int flags)

{

CheckPointCLOG();

CheckPointSUBTRANS();

CheckPointMultiXact();

CheckPointPredicate();

CheckPointRelationMap();

CheckPointBuffers(flags); /* performs all required fsyncs */

/* We deliberately delay 2PC checkpointingas long as possible */

CheckPointTwoPhase(checkPointRedo);

}

PostgreSQL啟動過程中的那些事十六:啟動進程三:CheckPointGuts刷出共享內(nèi)存里所有數(shù)據(jù)

CheckPointGuts 方法調(diào)用序列圖

CheckPointGuts 方法主要是通過調(diào)用提交事務(wù)日志管理器的方法 CheckPointClog ,子事務(wù)日志管理器的方法 CheckPointSUBTRANS ,多事務(wù)日志管理器的方法 CheckPointMultiXact ,支持序列化事務(wù)隔離級別的謂詞鎖模塊的方法 CheckPointPredicate ,目錄 / 系統(tǒng)表到文件節(jié)點映射模塊的方法 CheckPointRelationMap ,緩存管理器的方法 CheckPointBuffers ,兩階段提交模塊的方法 CheckPointTwoPhase 把共享內(nèi)存里的數(shù)據(jù)刷出并文件同步到磁盤。

其中 提交事務(wù)日志管理器的方法 CheckPointClog 、 子事務(wù)日志管理器的方法 CheckPointSUBTRANS 、多事務(wù)日志管理器的方法 CheckPointMultiXact 、多事務(wù)日志管理器的方法 CheckPointMultiXact 、支持序列化事務(wù)隔離級別的謂詞鎖模塊的方法 CheckPointPredicate 最后都調(diào)用了 SLRU 模塊的 SimpleLruFlush 方法,把相關(guān)共享內(nèi)存數(shù)據(jù)寫到磁盤,并調(diào)用 pg_fsync 方法把相關(guān)內(nèi)容文件同步到磁盤上對應(yīng)文件。

在緩存管理器的方法 CheckPointBuffers ,兩階段提交模塊的方法 CheckPointTwoPhase 里,因為沒有使用 SLRU 算法,直接調(diào)用 pg_fsync 方法把相關(guān)內(nèi)容文件同步到磁盤上對應(yīng)文件。

在目錄 / 系統(tǒng)表到文件節(jié)點映射模塊的方法 CheckPointRelationMap 里,在釋放 RelationMappingLock 時,會完成共享內(nèi)存里相關(guān)系統(tǒng)表和對應(yīng)物理文件映射的文件同步到磁盤工作。

我們看一下各種日志管理,日志對數(shù)據(jù)庫是至關(guān)重要的一部分,出現(xiàn)系統(tǒng)故障時,數(shù)據(jù)庫通過重放日志恢復(fù)數(shù)據(jù),保證數(shù)據(jù)庫一致性和完整性。

Pg 里有 XLOG CLOG SUBTRANS LOG MultiXactID LOG 四種事務(wù)日志, XLOG 是事務(wù)日志,就是平時常說的 REDOLOG ,記錄了事務(wù)操作數(shù)據(jù)庫的過程信息和事務(wù)最終狀態(tài); CLOG XLOG 里事務(wù)的提交狀態(tài)日志; SUBTRANS 是子事務(wù)日志, 為每一個事務(wù)存儲父事務(wù)ID。這是嵌套事務(wù)實現(xiàn)的基礎(chǔ)部分, SUBTRANS 僅需要為當(dāng)前打開的事務(wù)記住信息,沒有必要在崩潰并重啟后保留數(shù)據(jù); MultiXactID 是組合事務(wù)日志,由一組事務(wù) ID 組成, 是共享行鎖 shared-row-lock 實現(xiàn)的基礎(chǔ)部分,共享鎖鎖住的元組在其Xmax字段存儲MultiXactId。各種日志都存放在對應(yīng)的日志文件里。

有了文件就有了I/O,為了降低I/O開銷,pg設(shè)置了各種日志的緩存區(qū),由對應(yīng)的日志管理器管理日志的寫、文件同步和讀等日志維護工作。Pg使用簡單最近最少使用(SLRU)算法來管理事務(wù)日志。使用輕量鎖LWLock的 ControlLock 鎖保護整個緩沖區(qū),其中的每個緩沖塊(默認(rèn)8K)還有一個LWLock鎖保護,以控制并發(fā)操作。SLRU及事務(wù)日志的部分相關(guān)數(shù)據(jù)結(jié)構(gòu)在下面。

為CLOG控制鏈接到共享內(nèi)存數(shù)據(jù)結(jié)構(gòu)

static SlruCtlData ClogCtlData;

#define ClogCtl (&ClogCtlData)

為SUBTRANS控制鏈接到共享內(nèi)存數(shù)據(jù)結(jié)構(gòu)

static SlruCtlData SubTransCtlData;

#define SubTransCtl (&SubTransCtlData)

為MultiXact控制鏈接到共享內(nèi)存數(shù)據(jù)結(jié)構(gòu)

static SlruCtlData MultiXactOffsetCtlData;

static SlruCtlData MultiXactMemberCtlData;

#define MultiXactOffsetCtl (&MultiXactOffsetCtlData)

#define MultiXactMemberCtl (&MultiXactMemberCtlData)

typedef SlruCtlData * SlruCtl ;

/* SlruCtlData 是指向共享內(nèi)存里的活躍信息的非共享結(jié)構(gòu) */

typedef struct SlruCtlData

{

SlruShared shared ;

/* 這個標(biāo)志告訴 是否文件同步寫( pg_clog multixact 成員是 true,pg_subtrans pg_notify false */

bool do_fsync ;

/* 為截斷目的決定兩個頁號哪一個是更舊的。為了用 包裹 XID 算法( with wraparound XID arithmetic )做正確的事,這兒我們需要用事務(wù) ID 比較 */

bool (* PagePrecedes ) ( int , int );

/* SimpleLruInit 期間目錄被設(shè)置,并且從那以后不變。因為它總是相同的,它不必放到共享內(nèi)存里。 */

char Dir [64];

} SlruCtlData ;

共享內(nèi)存狀態(tài)

typedef struct SlruSharedData

{

LWLockId ControlLock ;

/* 由這個 SLRU 結(jié)構(gòu)管理的緩存塊號 */

int num_slots ;

/* 持有每一個緩存槽信息的數(shù)組。當(dāng)狀態(tài)是 EMPTY 緩存頁 / 塊號是未定義的,當(dāng)作

page_lru_count 。 */

char ** page_buffer ;

SlruPageStatus * page_status ;

bool * page_dirty ;

int * page_number ;

int * page_lru_count ;

LWLockId * buffer_locks ;

/* SLRU / 塊里的相關(guān)條目的 WAL 刷出 LSN 的可選數(shù)組。如果不是 0/NULL ,在寫緩存頁 / 塊前 我們必須刷出 WAL pg_clog true , multixact 、 pg_subtrans pg_notify false )。 Group_lsn[] 每緩存頁 / 塊槽有 lsn_groups_per_page 條目,在這個槽的緩存頁 / 塊上 SLRU 條目的一個臨近組 每一個緩存頁 / 塊槽 包含最高已知 LSN */

XLogRecPtr * group_lsn ;

int lsn_groups_per_page ;

/* 我們通過設(shè)置 page_lru_count[ slotno ] = ++cur_lru_count 標(biāo)記頁“最近使用”;最老舊頁因此是有表達式 cur_lru_count - page_lru_count[ slotno ] 值最高 / 大的那一個。這個數(shù)事實上包裹,但這個計算仍然工作 和緩存頁 / 塊的年齡(超過了 INT_MAX 數(shù))一樣長。 */

int cur_lru_count ;

/* latest_page_number 是當(dāng)前日志結(jié)尾的頁 / 塊號;這不是嚴(yán)格的數(shù)據(jù),因為我們僅用它避免包裹 swapping 出了最后的頁 / 塊。 */

int latest_page_number ;

} SlruSharedData ;

typedef SlruSharedData * SlruShared ;

/* 頁狀態(tài)代碼。注意這不包含 "dirty" 位。僅在 VALID 或者 WRIT_IN_PROGRESS 狀態(tài)里 page_dirty 能是 true ;在后面的例子 / 情況里 它暗示 從這次寫開始后頁又被搞臟 */

typedef enum

{

SLRU_PAGE_EMPTY , /* buffer is not in use */

SLRU_PAGE_READ_IN_PROGRESS , /* page is beingread in */

SLRU_PAGE_VALID , /* page is valid and not being written */

SLRU_PAGE_WRITE_IN_PROGRESS /* page is beingwritten out */

} SlruPageStatus ;

SLRU 算法的緩存區(qū)操作在下面,其中包括了本節(jié)多次調(diào)用的 SimpleLruFlush 方法,將緩存數(shù)據(jù)刷出并文件同步到磁盤。

extern Size SimpleLruShmemSize ( int nslots, int nlsns);

extern void SimpleLruInit ( SlruCtl ctl, const char *name, int nslots, int nlsns,

LWLockId ctllock, const char *subdir);

extern int SimpleLruZeroPage ( SlruCtl ctl, int pageno);

extern int SimpleLruReadPage ( SlruCtl ctl, int pageno, bool write_ok,

TransactionId xid);

extern int SimpleLruReadPage_ReadOnly ( SlruCtl ctl, int pageno,

TransactionId xid);

extern void SimpleLruWritePage ( SlruCtl ctl, int slotno);

extern void SimpleLruFlush ( SlruCtl ctl, bool checkpoint);

extern void SimpleLruTruncate ( SlruCtl ctl, int cutoffPage);

extern bool SlruScanDirectory ( SlruCtl ctl, int cutoffPage, bool doDeletions);

就到這兒吧。

------------
轉(zhuǎn)載請著明出處,來自博客:
blog.csdn.net/beiigang
beigang.iteye.com




PostgreSQL啟動過程中的那些事十六:啟動進程三:CheckPointGuts刷出共享內(nèi)存里所有數(shù)據(jù)


更多文章、技術(shù)交流、商務(wù)合作、聯(lián)系博主

微信掃碼或搜索:z360901061

微信掃一掃加我為好友

QQ號聯(lián)系: 360901061

您的支持是博主寫作最大的動力,如果您喜歡我的文章,感覺我的文章對您有幫助,請用微信掃描下面二維碼支持博主2元、5元、10元、20元等您想捐的金額吧,狠狠點擊下面給點支持吧,站長非常感激您!手機微信長按不能支付解決辦法:請將微信支付二維碼保存到相冊,切換到微信,然后點擊微信右上角掃一掃功能,選擇支付二維碼完成支付。

【本文對您有幫助就好】

您的支持是博主寫作最大的動力,如果您喜歡我的文章,感覺我的文章對您有幫助,請用微信掃描上面二維碼支持博主2元、5元、10元、自定義金額等您想捐的金額吧,站長會非常 感謝您的哦?。?!

發(fā)表我的評論
最新評論 總共0條評論
主站蜘蛛池模板: 常宁市| 龙南县| 海原县| 玉田县| 西安市| 鹤岗市| 温宿县| 乡城县| 安仁县| 文登市| 南平市| 沙洋县| 木里| 合水县| 高要市| 乌兰浩特市| 阳原县| 阜康市| 荆门市| 黔江区| 麻栗坡县| 邵阳县| 宁乡县| 西藏| 华安县| 治县。| 信阳市| 梓潼县| 曲水县| 大理市| 吉木乃县| 商洛市| 桑日县| 德阳市| 鱼台县| 思茅市| 成都市| 罗定市| 岢岚县| 交城县| 象州县|