导读:数据库
以前已经写了关于wal记录的结构、wal记录的写入的博客,流复制、PITR、数据库启动、逻辑复制等PG功能都须要借助wal日志,他们是怎样读取wal日志记录的呢?这一篇博客将会讲解。函数
pg内核代码中读取wal有固定的程式。以下结构:工具
XLogReaderAllocate()
XLogFindNextRecord()
for (;;)
{
XLogReadRecord();
…
}post
XLogReaderAllocate(XLogPageReadCB pagereadfunc, void *private_data)
函数用来作读取的预处理,数据初始化、空间分配、page读取函数注册等。
第一个参数pagereadfunc是一个函数指针,指向的函数功能为,读取page的数据、wal日志文件切换。.net
全部读取wal日志的程序都会都会为本身定制一个pagereadfunc函数,如代码中:指针
XLogDumpReadPage→pg_waldump工具的读取函数。日志
XLogPageRead→recovery过程读取wal的函数code
read_page→逻辑复制使用的函数orm
SimpleXLogPageRead→pg_rewind使用的函数
XLogFindNextRecord(XLogReaderState *state, XLogRecPtr RecPtr)
获取RecPtr位置以后的第一个记录的位置,做为XLogReadRecord函数的入参
XLogRecord *XLogReadRecord(XLogReaderState *state, XLogRecPtr RecPtr, char **errormsg)
①从page中按照《postgres预写式日志的内核实现详解-wal结构》的结构读取记录
②经过DecodeXLogRecord()函数将读取到的record记录进行初步解析,获取到的实际数据存储到XLogReaderState结构体中。
#define XLogRecGetTotalLen(decoder) ((decoder)->decoded_record->xl_tot_len) #define XLogRecGetPrev(decoder) ((decoder)->decoded_record->xl_prev) #define XLogRecGetInfo(decoder) ((decoder)->decoded_record->xl_info) #define XLogRecGetRmid(decoder) ((decoder)->decoded_record->xl_rmid) #define XLogRecGetXid(decoder) ((decoder)->decoded_record->xl_xid) #define XLogRecGetOrigin(decoder) ((decoder)->record_origin) #define XLogRecGetData(decoder) ((decoder)->main_data) #define XLogRecGetDataLen(decoder) ((decoder)->main_data_len) #define XLogRecHasAnyBlockRefs(decoder) ((decoder)->max_block_id >= 0) #define XLogRecHasBlockRef(decoder, block_id) \ ((decoder)->blocks[block_id].in_use) #define XLogRecHasBlockImage(decoder, block_id) \ ((decoder)->blocks[block_id].has_image) #define XLogRecBlockImageApply(decoder, block_id) \ ((decoder)->blocks[block_id].apply_image)
使用上述宏就能够获取wal记录里的数据。