postgres預寫式日誌的核心實現詳解-wal記錄讀取
之前已經寫了關於wal記錄的結構、wal記錄的寫入的部落格,流複製、PITR、資料庫啟動、邏輯複製等PG功能都需要藉助wal日誌,他們是怎樣讀取wal日誌記錄的呢?這一篇部落格將會講解。
pg核心程式碼中讀取wal有固定的程式。如下結構:
XLogReaderAllocate()
XLogFindNextRecord()
for (;;)
{
XLogReadRecord();
…
}
XLogReaderAllocate(XLogPageReadCB pagereadfunc, void *private_data)
函式用來做讀取的預處理,資料初始化、空間分配、page讀取函式註冊等。
第一個引數pagereadfunc是一個函式指標,指向的函式功能為,讀取page的資料、wal日誌檔案切換。
所有讀取wal日誌的程式都會都會為自己定製一個pagereadfunc函式,如程式碼中:
XLogDumpReadPage→pg_waldump工具的讀取函式。
XLogPageRead→recovery過程讀取wal的函式
read_page→邏輯複製使用的函式
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記錄裡的資料。