(完整流程在log_heap_update)
(1)用两个registered_buffers记录新旧页面buffer
XLogRegisterBuffer(0, newbuf, bufflags);
XLogRegisterBuffer(1, oldbuf, REGBUF_STANDARD);
(2)注册maindata【SizeOfHeapUpdate大小:14】
XLogRegisterData((char *) &xlrec, SizeOfHeapUpdate);
/* 关于 update / hot update需要知道的信息 */
typedef struct xl_heap_update
{
TransactionId old_xmax; /* xmax of the old tuple */
OffsetNumber old_offnum; /* old tuple's offset */
uint8 old_infobits_set; /* infomask bits to set on old tuple */
uint8 flags;
TransactionId new_xmax; /* xmax of the new tuple */
OffsetNumber new_offnum; /* new tuple's offset */
/*
* If XLOG_HEAP_CONTAINS_OLD_TUPLE or XLOG_HEAP_CONTAINS_OLD_KEY flags are
* set, a xl_heap_header struct and tuple data for the old tuple follows.
*/
} xl_heap_update;
maindata专用指针
(3)新页面注册元组头【SizeOfHeapHeader大小:5】
XLogRegisterBufData(0, (char *) &xlhdr, SizeOfHeapHeader);
(4)新页面注册元组数据【数据大小:9】
XLogRegisterBufData(0,((char *) newtup->t_data) + SizeofHeapTupleHeader, newtup->t_len - SizeofHeapTupleHeader - suffixlen);
newbuffer在registered_buffers[0]中记录,挂两个rdata
oldbuffer在registered_buffers[1]中记录,没有挂rdata
跨页UPDATE场景下XLogRecordAssemble返回值hdr_rdt都挂了啥?
hdr_rdt挂四个元素:
----------------------------------------------------------------------------------------
【XLogRecord结构】
XLogRecord << hdr_rdt.data = hdr_scratch;
----------------------------------------------------------------------------------------
【头信息,和下面数据信息一一对应】
(新页面)XLogRecordBlockHeader << memcpy(scratch, &bkpb, SizeOfXLogRecordBlockHeader);
(无)XLogRecordBlockImageHeader << memcpy(scratch, &bimg, SizeOfXLogRecordBlockImageHeader);
(无)XLogRecordBlockCompressHeader << memcpy(scratch, &cbimg, SizeOfXLogRecordBlockCompressHeader);
(新页面)RelFileNode << memcpy(scratch, ®buf->rnode, sizeof(RelFileNode));
(新页面)BlockNumber << memcpy(scratch, ®buf->block, sizeof(BlockNumber));
(旧页面)XLogRecordBlockHeader
(旧页面)BlockNumber
----------------------------------------------------------------------------------------
【数据】
(3)新页面注册元组头【SizeOfHeapHeader大小:5】
----------------------------------------------------------------------------------------
(4)新页面注册元组数据【数据大小:9】
----------------------------------------------------------------------------------------
【MAINDATA】
(2)注册maindata【SizeOfHeapUpdate大小:14】
具体数据:
4: *hdr_rdt->next->next->next = {next = 0x0, data = 0x7ffc19800b70 "\030w\033", len = 14} 【MAINDATA】
3: *hdr_rdt->next->next = {next = 0x29e9fb0, data = 0x2a4a837 "", len = 9} 【数据:元组数据】
2: *hdr_rdt->next = {next = 0x29e9fe0, data = 0x7ffc19800b60 "\002", len = 5} 【数据:元组头】
1: hdr_rdt = {next = 0x29e9fc8, data = 0x29ea1c8 "6", len = 46} 【头信息】
一条XLOG内部四部分:
所以对于PG来说,不存在mysql的mtr(mini trnasaction),一条XLOG内部的所有操作需要是原子的(如何保证?一条XLOG在做得过程中,数据库redo逻辑会保证相关页带锁,无法读到中间态)。