如题所述
本节重点跟踪分析了XLogRecordAssemble函数中对FPW(full-page-write)的处理过程。
全局静态变量
XLogRecordAssemble使用的全局变量包括hdr_rdt/hdr_scratch/rdatas等.
宏定义
XLogRegisterBuffer函数使用的flags
XLogRecData
xloginsert.c中的函数构造一个XLogRecData结构体链用于标识最后的WAL记录
registered_buffer
对于每一个使用XLogRegisterBuffer注册的每个数据块,填充到registered_buffer结构体中
rmid(Resource Manager ID)的定义
0 XLOG
1 Transaction
2 Storage
3 CLOG
4 Database
5 Tablespace
6 MultiXact
7 RelMap
8 Standby
9 Heap2
10 Heap
11 Btree
12 Hash
13 Gin
14 Gist
15 Sequence
16 SPGist
XLogRecordAssemble函数从已注册的数据和缓冲区中组装XLOG record到XLogRecData链中,组装完成后可以使用XLogInsertRecord()函数插入到WAL buffer中.
详见 上一小节
场景二:在数据表中插入第n条记录
测试脚本如下:
设置断点,进入XLogRecordAssemble
输入参数:
rmid=10即0x0A --> Heap
info=0 '\000'
RedoRecPtr=5509173376,十六进制值为0x00000001485F5080
doPageWrites=true,需要full-page-write
fpw_lsn=0x7ffd7eb51408(fpw是full-page-write的简称,注意该变量仍未赋值)
接下来是变量赋值.
hdr_scratch的定义为:static char *hdr_scratch = NULL;
hdr_rdt的定义为:static XLogRecData hdr_rdt;
配置hdr_rdt(用于存储header信息)
full-page-write's LSN初始化
开始循环,获取regbuf.
regbuf是使用
注意:
在内存中,main data已由函数XLogRegisterData注册,由mainrdata_head和mainrdata_last指针维护,本例中,填充了xl_heap_insert结构体.
block data由XLogRegisterBuffer初始化,通过XLogRegisterBufData注册(填充)数据,分别是xl_heap_header结构体和实际数据(实质上是char *指针,最终填充的数据,由组装器确定).
1.main data
2.block data -> xl_heap_header
3.block data -> tuple data
查看地址0x1feb07f开始的21个字节数据,指向实际的数据.
第一个字段:首字节0 '\000'是类型标识符(INT,注:未最终确认),后续4个字节是32bit整型0x00002000,即整数8192.
第二个字段:首字节 17 '\021'是类型标识符(VARCHAR,注:未最终确认),后续是实际数据,即C2-8192
第三个字段:与第二个字段类似(C3-8192)
4.block data -> backup block image
这部分内容由XLogRecordAssemble()函数填充.
继续执行后续逻辑,regbuf->flags=0x08表示REGBUF_STANDARD(标准的page layout)
doPageWrites = T,需要执行full-page-write.
page_lsn = 5509173336,十六进制值为0x00000001485F5058,逻辑ID为0x00000001,物理ID为0x00000048,segment file文文件名称为00000001 00000001 00000048(时间线为0x00000001),文件内偏移为0x5F5058.
需要执行full-page-write
判断是否需要tuple data(needs_data标记)
配置BlockHeader
要求包含块镜像(FPI),获取相应的page(64bit的指针)
查看page内容
换用字符格式查看0x7f391f91d330开始的数据
标准块(REGBUF_STANDARD),获取lower&upper,并设置hole信息
没有启用压缩,则不尝试压缩block
设置标记BKPBLOCK_HAS_IMAGE
设置相关信息
设置标记BKPIMAGE_APPLY
没有压缩存储,设置相关信息
设置rdt_datas_last变量,构建hdr_rdt链表,分别指向hole前面部分hole后面部分
查看hdr_rdt相关信息
设置大小
不需要处理tuple data,不是同一个REL
拷贝头部信息到scratch缓冲区中
包含FPI,追加SizeOfXLogRecordBlockImageHeader
不是同一个REL,追加RelFileNode
后跟blocknumber
继续下一个block
已处理完毕,接下来,是XLOG Record origin(不需要)
接下来是main data,使用XLR_BLOCK_ID_DATA_SHORT格式
调整rdt_datas_last变量信息,调整总大小
调整hdr_rdt信息
计算CRC
填充记录头部信息的其他域字段.
返回hdr_rdt
DONE!
Write Ahead Logging — WAL
PostgreSQL 源码解读(4)- 插入数据#3(heap_insert)
PostgreSQL 事务日志WAL结构浅析
PostgreSQL 源码解读(110)- WAL#6(Insert&WAL - XLogRecordAssemble记录组装函数)
PG Source Code