Postgresql源码(17)update生成XLOG过程&内容解析

2022-05-12 08:32:38 浏览数 (1)

(完整流程在log_heap_update)

1 注册阶段

(1)用两个registered_buffers记录新旧页面buffer

代码语言:javascript复制
XLogRegisterBuffer(0, newbuf, bufflags);
XLogRegisterBuffer(1, oldbuf, REGBUF_STANDARD);

(2)注册maindata【SizeOfHeapUpdate大小:14】

代码语言:javascript复制
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】

代码语言:javascript复制
XLogRegisterBufData(0, (char *) &xlhdr, SizeOfHeapHeader);

(4)新页面注册元组数据【数据大小:9】

代码语言:javascript复制
XLogRegisterBufData(0,((char *) newtup->t_data)   SizeofHeapTupleHeader, newtup->t_len - SizeofHeapTupleHeader - suffixlen);

newbuffer在registered_buffers[0]中记录,挂两个rdata

oldbuffer在registered_buffers[1]中记录,没有挂rdata

2 组装阶段

跨页UPDATE场景下XLogRecordAssemble返回值hdr_rdt都挂了啥?

hdr_rdt挂四个元素:

代码语言:javascript复制
----------------------------------------------------------------------------------------
【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, &regbuf->rnode, sizeof(RelFileNode));
(新页面)BlockNumber                         << memcpy(scratch, &regbuf->block, sizeof(BlockNumber));
(旧页面)XLogRecordBlockHeader
(旧页面)BlockNumber   
----------------------------------------------------------------------------------------
【数据】
(3)新页面注册元组头【SizeOfHeapHeader大小:5】
----------------------------------------------------------------------------------------
(4)新页面注册元组数据【数据大小:9】
----------------------------------------------------------------------------------------
【MAINDATA】
(2)注册maindata【SizeOfHeapUpdate大小:14】

具体数据:

代码语言:javascript复制
4: *hdr_rdt->next->next->next = {next = 0x0,       data = 0x7ffc19800b70 "30w33", len = 14}  【MAINDATA】
3: *hdr_rdt->next->next =       {next = 0x29e9fb0, data = 0x2a4a837 "",               len = 9}   【数据:元组数据】
2: *hdr_rdt->next =             {next = 0x29e9fe0, data = 0x7ffc19800b60 "02",      len = 5}   【数据:元组头】
1:  hdr_rdt =                   {next = 0x29e9fc8, data = 0x29ea1c8 "6",              len = 46}  【头信息】

3 生成几条XLOG?

一条XLOG内部四部分:

  1. 日志头XLogRecord
  2. blockheader集合
  3. block集合
  4. maindata

所以对于PG来说,不存在mysql的mtr(mini trnasaction),一条XLOG内部的所有操作需要是原子的(如何保证?一条XLOG在做得过程中,数据库redo逻辑会保证相关页带锁,无法读到中间态)

0 人点赞