以heap_insert为例,简述WAL的插入过程。


在构建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语句的元组数据等。


下面首先介绍相关数据结构。


1、数据结构

HeapTupleData

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_header

/*
?*?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;

XLogRecData

/*
?*?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_buffer

/*
?*?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;

2、heap_insert涉及WAL的流程

?image.png

第一步中,得到如下结果,mainrdata_last保存rdata[0],存储的是xl_heap_insert结构:

image.png

第二步,得到如下结果,取registered_buffer[0],其rdata_head->next指向rdata[1],存储tuple记录的头信息:

image.png

接着进入第三步,取rdata[2],将其放到rdata[1]->next中,即加入registered_buffers[0]的rdata_head链表中,存储TUPLE值:

image.png

以上是构建WAL记录的准备阶段,下一节介绍WAL的构建及其通用结构。