導讀:數據庫
以前已經寫了關於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記錄裏的數據。