以heap_insert爲例,簡述WAL的插入過程。node
在構建WAL日誌記錄的過程當中主要涉及2個數據變量:static XLogRecData *rdatas數組和static registered_buffer *registered_buffers數組。這兩個數組分別用來保存WAL數據和管理rdatas鏈表。數組
主要涉及3個重要的函數:XLogRegisterData、XLogRegisterBuffer和XLogRegisterBufData。這三個函數的做用分別是將WAL記錄的特殊結構體數據註冊到WAL,好比heap_insert中的xl_heap_insert結構體;將涉及到的buf註冊到wal記錄,好比heap_insert中page頁賦予regbuf->page;將元組內容註冊到WAL記錄,好比insert語句的元組數據等。數據結構
下面首先介紹相關數據結構。ide
一、數據結構函數
HeapTupleDataui
typedef struct HeapTupleData { uint32 t_len; /* length of *t_data */ ItemPointerData t_self; /* SelfItemPointer */ Oid t_tableOid; /* table the tuple came from */ HeapTupleHeader t_data; /* -> tuple header and data */ } HeapTupleData;
xl_heap_headerthis
/* * We don't store the whole fixed part (HeapTupleHeaderData) of an inserted * or updated tuple in WAL; we can save a few bytes by reconstructing the * fields that are available elsewhere in the WAL record, or perhaps just * plain needn't be reconstructed. These are the fields we must store. * NOTE: t_hoff could be recomputed, but we may as well store it because * it will come for free due to alignment considerations. */ typedef struct xl_heap_header { uint16 t_infomask2; uint16 t_infomask; uint8 t_hoff; } xl_heap_header;
xl_heap_insert日誌
/* This is what we need to know about insert */ typedef struct xl_heap_insert { OffsetNumber offnum; /* inserted tuple's offset */ uint8 flags; /* xl_heap_header & TUPLE DATA in backup block 0 */ } xl_heap_insert;
XLogRecDatait
/* * The functions in xloginsert.c construct a chain of XLogRecData structs * to represent the final WAL record. */ typedef struct XLogRecData { struct XLogRecData *next; /* next struct in chain, or NULL */ char *data; /* start of rmgr data to include */ uint32 len; /* length of rmgr data to include */ } XLogRecData;
registered_bufferio
/* * For each block reference registered with XLogRegisterBuffer, we fill in * a registered_buffer struct. */ typedef struct { bool in_use; /* is this slot in use? */ uint8 flags; /* REGBUF_* flags */ RelFileNode rnode; /* identifies the relation and block */ ForkNumber forkno; BlockNumber block; Page page; /* page content */ uint32 rdata_len; /* total length of data in rdata chain */ XLogRecData *rdata_head; /* head of the chain of data registered with this block */ XLogRecData *rdata_tail; /* last entry in the chain, or &rdata_head if empty */ XLogRecData bkp_rdatas[2]; /* temporary rdatas used to hold references to * backup block data in XLogRecordAssemble() */ /* buffer to store a compressed version of backup block image */ char compressed_page[PGLZ_MAX_BLCKSZ]; } registered_buffer;
二、heap_insert涉及WAL的流程
第一步中,獲得以下結果,mainrdata_last保存rdata[0],存儲的是xl_heap_insert結構:
第二步,獲得以下結果,取registered_buffer[0],其rdata_head->next指向rdata[1],存儲tuple記錄的頭信息:
接着進入第三步,取rdata[2],將其放到rdata[1]->next中,即加入registered_buffers[0]的rdata_head鏈表中,存儲TUPLE值:
以上是構建WAL記錄的準備階段,下一節介紹WAL的構建及其通用結構。