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]