1、背景
常見的高可用架構中,若是master掛了且有數據沒有同步到備,高可用系統會提高備爲主對外服務。對於老主有可能再以備的身份加入集羣時,可能搭建流複製關係失敗。能夠用pg_rewind工具使主備的數據一致。node
2、pg_rewind原理
3、相關代碼數據庫
一、每一個文件(目錄)的差別被記錄在結構體 file_entry_t 中,其定義以下 typedef struct file_entry_t { char *path; file_type_t type; file_action_t action; /* for a regular file */ size_t oldsize; size_t newsize; Bool isrelfile; /* is it a relation data file? */ datapagemap_t pagemap; /* for a symlink */ char *link_target; struct file_entry_t *next; } file_entry_t; 二、文件類型 typedef enum { FILE_TYPE_REGULAR,//常規文件 FILE_TYPE_DIRECTORY,//目錄 FILE_TYPE_SYMLINK//軟鏈接 } file_type_t; 三、對應文件的操做action typedef enum { FILE_ACTION_CREATE, /* 建立目錄或者軟連接: create_target(entry)*/ FILE_ACTION_COPY, /* 複製整個文件或者重寫已存在的文件: fetch_file_range(entry->path, 0, entry->newsize);*/ FILE_ACTION_COPY_TAIL, /* 從source中拷貝從oldsize到newsize的部分 fetch_file_range(entry->path, entry->oldsize, entry->newsize)*/ FILE_ACTION_NONE, /* 無操做 */ FILE_ACTION_TRUNCATE, /* 裁剪target集羣文件到'newsize'大小: truncate_target_file(entry->path, entry->newsize)*/ FILE_ACTION_REMOVE /* 刪除本地文件/目錄/軟連接: remove_target(entry)*/ } file_action_t; 四、其餘變量解讀 isrefile 表示該文件是不是一個表數據文件,表數據文件的路徑要知足如下幾個條件: isRelDataFile(path): global/ 目錄下的文件,即數據庫共享的表文件目錄下的文件 base/ 目錄下的文件,即默認tablespace的表文件目錄下的文件 pg_tblspc/&rnode.spcNode/TABLESPACE_VERSION_DIRECTORY/目錄下的文件,即其餘tablespace 的表文件目錄下的文件,其中PG_9.4_201403261 與版本相關 文件名符合的格式 pagemap (怎麼用?extractPageInfo)存儲了一個bitmap,每一位存儲了對應的目的集羣文件中的每一個page 從兩個集羣的分叉點以後是否發生了變化,1表明發生變化,0表明未變化。 oldsize 表明目的集羣該文件的大小,newsize 表明源集羣該文件的大小。pg_rewind 中經過源集羣和目的集羣的對應文件大小比較或者文件(目錄)是否存在,指定文件的處理action,例如: oldsize > newsize: action=FILE_ACTION_TRUNCATE oldsize < newsize: action=FILE_ACTION_COPY_TAIL 若是文件不存在,則action=FILE_ACTION_COPY,PG_VERSION文件除外 若是目錄不存在,則action=FILE_ACTION_CREATE 若是文件多餘,則action=FILE_ACTION_REMOVE 以上動做由函數process_target_file和process_source_file一塊兒處理。只在process_target_file設置FILE_ACTION_REMOVE 五、提取wal日誌獲取更改頁的步驟: extractPageInfo: for (block_id = 0; block_id <= record->max_block_id; block_id++){ if (!XLogRecGetBlockTag(record, block_id, &rnode, &forknum, &blkno)) continue; /* We only care about the main fork; others are copied in toto */ if (forknum != MAIN_FORKNUM)//MAIN_FORKNUM是什麼意思? continue; process_block_change(forknum, rnode, blkno); } 六、pagemap中的bitmap pg_rewind 工具執行須要打開full_page_writes,而打開了full_page_writes 以後,checkpoint 後每一個數據頁的第一次修改對應的數據頁的所有內容都會寫在WAL日誌記錄中,因此pg_rewind 能夠根據WAL 日誌的組織結構很容易的找到對應已經修改的數據頁信息,並把對應的file_entry_t 的bitmap 置爲1。 XLogRecGetBlockTag:XLogReaderState.blocks[XLR_MAX_BLOCK_ID + 1]