postgres预写式日志的内核实现详解-heap类型

原创
2018/11/28 11:30
阅读数 2.9K

  导读:

    postgres预写式日志的内核实现详解-概述

 

heap(RM_HEAP_ID)是数据库对任何logged表进行insert、delete、update操作后所产生的日志类型,如下为heap类型的wal子类型。

#define XLOG_HEAP_INSERT		0x00
#define XLOG_HEAP_DELETE		0x10
#define XLOG_HEAP_UPDATE		0x20
/* 0x030 is free, was XLOG_HEAP_MOVE */
#define XLOG_HEAP_HOT_UPDATE	0x40
#define XLOG_HEAP_CONFIRM		0x50
#define XLOG_HEAP_LOCK			0x60
#define XLOG_HEAP_INPLACE		0x70

 

 

XLOG_HEAP_INSERT

此wal子类型是在执行插入语句时所记录的wal日志。代码在heap_insert()函数中。reod函数为heap_xlog_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;

offnum字段:插入的元组在page的相对位置

flags字段:标志位

#define XLH_INSERT_ALL_VISIBLE_CLEARED			(1<<0)//VM文件相关
#define XLH_INSERT_LAST_IN_MULTI				(1<<1)//muti insert相关
#define XLH_INSERT_IS_SPECULATIVE				(1<<2)//预测插入,insert...on conflict相关
#define XLH_INSERT_CONTAINS_NEW_TUPLE			(1<<3)//wal记录即使为fpw,也写入新元组数据(logical模式)

此wal类型中可能包含的数据

①xl_heap_insert结构:一定存在,使用XLogRegisterData()注册。

②插入元组所在的page数据:可能存在,使用XLogRegisterBuffer()注册。

③插入的元组数据:可能存在,使用XLogRegisterBufData()注册。

 

XLOG_HEAP_DELETE

是在执行删除语句时所记录的wal日志。代码在heap_delete()函数中。redo函数为heap_xlog_delete()

特定描述结构体

typedef struct xl_heap_delete
{
	TransactionId xmax;			/* xmax of the deleted tuple */
	OffsetNumber offnum;		/* deleted tuple's offset */
	uint8		infobits_set;	/* infomask bits */
	uint8		flags;
} xl_heap_delete;

xmax:记录删除元组的xmax,redo时用以填充元组头数据

offnum:删除的元组在page的相对位置

infobits_set:记录元组的t_infomask和t_infomask2的值,redo时用以填充元组头数据

fiags:标志位

#define XLH_DELETE_ALL_VISIBLE_CLEARED			(1<<0)//VM文件相关
#define XLH_DELETE_CONTAINS_OLD_TUPLE			(1<<1)//一定包含旧元组数据
#define XLH_DELETE_CONTAINS_OLD_KEY				(1<<2)//一定包含旧KEY,REPLICA IDENTITY相关
#define XLH_DELETE_IS_SUPER						(1<<3)//预测插入数据的删除

此wal类型中可能包含的数据

①xl_heap_delete结构体:一定存在,使用XLogRegisterData()注册。

②删除元组所在的page数据:可能存在,使用XLogRegisterBuffer()注册。

③删除的元组数据:可能存在,使用XLogRegisterData()注册。

④删除的元组的key:可能存在,使用XLogRegisterData()注册。

 

XLOG_HEAP_UPDATE/XLOG_HEAP_HOT_UPDATE

XLOG_HEAP_UPDATE是执行一个非热更新时记录的wal日志。

XLOG_HEAP_HOT_UPDATE是执行一个热更新时记录的wal日志。

代码在log_heap_update()函数中,redo函数为heap_xlog_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;

old_xmax:记录update旧元组的xmax,redo时用以填充元组头数据

old_offnum:记录旧元组在其page中的相对位置

old_infobits_set:记录旧元组的t_infomask和t_infomask2的值,redo时用以填充元组头数据

new_xmax:记录新元组的xmax

new_offnum:记录新元组在其page中的相对位置

flags:标志位

/* PD_ALL_VISIBLE was cleared */
#define XLH_UPDATE_OLD_ALL_VISIBLE_CLEARED		(1<<0)//vm文件相关
/* PD_ALL_VISIBLE was cleared in the 2nd page */
#define XLH_UPDATE_NEW_ALL_VISIBLE_CLEARED		(1<<1)//vm文件相关
#define XLH_UPDATE_CONTAINS_OLD_TUPLE			(1<<2)//一定包含旧元组数据
#define XLH_UPDATE_CONTAINS_OLD_KEY				(1<<3)//一定包含旧元组key
#define XLH_UPDATE_CONTAINS_NEW_TUPLE			(1<<4)//即使本wal记录为fpw,也保留新元组数据(logical模式)
#define XLH_UPDATE_PREFIX_FROM_OLD				(1<<5)//新旧数据比较,记录从前面字段开始没有变化的字段数
#define XLH_UPDATE_SUFFIX_FROM_OLD				(1<<6)//新旧数据比较,记录从后面字段开始没有变化的字段数

当新元组和旧元组在同一个page的时候,wal记录中就不用包含所有的新元组的数据,只包含prefixlen和suffixlen之间的数据。XLH_UPDATE_PREFIX_FROM_OLD和XLH_UPDATE_SUFFIX_FROM_OLD用来标记在wal记录中保存了prefixlen和suffixlen位置。

此wal类型中可能包含的数据

①xl_heap_update结构体:一定存在,使用XLogRegisterData()注册。

②旧元组所在的page数据:可能存在,使用XLogRegisterBuffer()注册。

③旧元组数据:可能存在,使用XLogRegisterData()注册。

④旧元组的key:可能存在,使用XLogRegisterData()注册。

⑤新元组所在的page数据:可能存在,使用XLogRegisterBuffer()注册。

⑥新元组数据:可能存在,使用XLogRegisterBufData()注册。

⑦prefixlen:可能存在,使用XLogRegisterBufData()注册。

⑧suffixlen:可能存在,使用XLogRegisterBufData()注册。

⑨部分新元组数据:可能存在,使用XLogRegisterBufData()注册。


XLOG_HEAP_MOVE 

此wal日志类型一直没有使用,没查到原因,不过在pg11上此项改为XLOG_HEAP_TRUNCATE,为truncate语句也记录wal日志。

暂时没有研究这个新的wal类型


XLOG_HEAP_CONFIRM 

插入语句如果有on conflict子句,那么可能会有一个确认插入的XLOG_HEAP_CONFIRM记录。

代码在heap_finish_speculative()函数中,redo函数为heap_xlog_confirm()。

特定描述结构体

typedef struct xl_heap_confirm
{
	OffsetNumber offnum;		/* confirmed tuple's offset on page */
} xl_heap_confirm;

offnum:确认插入的元组在其page的相对位置

此wal类型中可能包含的数据

①xl_heap_confirm结构体:一定存在,使用XLogRegisterData()注册。

②元组所在的page数据:可能存在,使用XLogRegisterBuffer()注册。

 

XLOG_HEAP_LOCK

在锁定元组时,xmax会从一个有效值改变为另一个有效值,在此种情况下使用这个wal类型完成xid消耗的记录,

在heap_update()函数和heap_lock_tuple()函数中都会有这个wal子类型的产生。redo函数为heap_xlog_lock

特定描述结构体

typedef struct xl_heap_lock
{
	TransactionId locking_xid;	/* might be a MultiXactId not xid */
	OffsetNumber offnum;		/* locked tuple's offset on page */
	int8		infobits_set;	/* infomask and infomask2 bits to set */
	uint8		flags;			/* XLH_LOCK_* flag bits */
} xl_heap_lock;

locking_xid:锁定元祖产生的中间xid

offnum:元组在其page的位置

old_infobits_set:记录元组的t_infomask和t_infomask2的值,redo时用以填充元组头数据

flags:标志位

#define XLH_LOCK_ALL_FROZEN_CLEARED		0x01//VM文件相关

此wal类型中可能包含的数据

①xl_heap_lock结构体:一定存在,使用XLogRegisterData()注册。

②元组所在的page数据:可能存在,使用XLogRegisterBuffer()注册。


XLOG_HEAP_INPLACE

更新一个元组时,在原位置发生改动,不产生新的元组。此情况只在更新一些系统表时发生。

代码在heap_inplace_update()函数中。redo函数为heap_xlog_inplace()。

特定描述结构体

typedef struct xl_heap_inplace
{
	OffsetNumber offnum;		/* updated tuple's offset on page */
	/* TUPLE DATA FOLLOWS AT END OF STRUCT */
} xl_heap_inplace;

offnum:元组在其page的位置

此wal类型中可能包含的数据

①xl_heap_inplace结构体:一定存在,使用XLogRegisterData()注册。

②元组所在的page数据:可能存在,使用XLogRegisterBuffer()注册。

③更新的数据:可能存在,使用XLogRegisterBufData()注册。

 

回到概述页

展开阅读全文
加载中
点击引领话题📣 发布并加入讨论🔥
0 评论
0 收藏
0
分享
返回顶部
顶部