1.3 PG如何使用日志进行恢复
1.3.1数据结构分析
1.3.1.1 xlog日志的结构
PG日志格式 图
逻辑日志 = 诸多物理日志文件之和
物理日志文件名称:
文件名 = 时间线 + logId(日志号) + segmented(段号)
说明:
时间线、logId、segmentId等每一部分都是16进制的八位数,文件名共24个字符,这样从物理文件的角度讲,每个日志文件对应一个“段”。
物理日志文件结构:
(1) 每个段文件大小为16M
(2) 每个日志文件分为256个段(segment)
(3) 每个逻辑日志文件大小为256*16=4096M=4G
说明:
这样的结构,说明当日志文件从“000000010000000000000000”变为“000000010000000100000000”时,实际上增加了256个物理文件,但逻辑上却只增加了1个文件
段文件结构:
XLOG_BLCKSZ = 8192
所以,每个段文件中,可以有 (16*1024*1024)/ XLOG_BLCKSZ = 2048 个块,每一个这样的块称为“页”(即:每页有8个1024大小,即8k;注意,在xlog的共享缓存中定义有8个缓存与此对应――“ XLogCtl->XLogCacheBlck = XLOGbuffers - 1;”)。
但是,一条日志记录有可能很大,会“跨”多个页。
页的格式:
页有页头,页通常有两种情况:普通页与段起始页。
普通页头结构:普通的页的页头标识,非一个段文件的首页
typedef struct XLogPageHeaderData
{
uint16 xlp_magic; /* magic value for correctness checks */
uint16 xlp_info; /* flag bits, see below */
TimeLineID xlp_tli; /* TimeLineID of first record on page */
XLogRecPtr xlp_pageaddr; /* XLOG address of this page */
} XLogPageHeaderData;
段起始页结构:如果本页是物理日志文件即一个段的首页,则用如下结构标识;
typedef struct XLogLongPageHeaderData
{
XLogPageHeaderData std; /* standard header fields */
uint64 xlp_sysid; /* system identifier from pg_control */
uint32 xlp_seg_size; /* just as a cross-check */
uint32 xlp_xlog_blcksz; /* just as a cross-check */
} XLogLongPageHeaderData;
日志记录格式:
xlog日志记录= xlog记录头部 + 记录体
= XlogRecord + XLogRecData
说明:
(1) Xlog记录头部的结构
存在于XLOG.H文件中
typedef struct XLogRecord
{
crc64 xl_crc; /* 记录的循环冗余校验码*/
XLogRecPtr xl_prev; /* 指向前一个日志记录的指针*/
TransactionId xl_xid; /* 事务Id */
uint32 xl_len; /* rmgr data的长度 */
uint8 xl_info; /*标志位,每一位代表的具体含义见下面的解释 */
/*对应“XLogInsert”函数中的第二个参数“uint8 info”*/
RmgrId xl_rmid; /* 此记录使用的resource manager 的ID,根据使用的资源 不同,Id长度可能不同*/
/*对应“XLogInsert”函数中的第二个参数“RmgrId rmid”*/
} XLogRecord;
xl_info标志位的含义:
XLOG使用xl_info的低4位,rgmr使用其高4位。
目前系统支持在一个XLOG record中最多处理三个磁盘块的日志信息。使用xl_info中的标志位来标记XLOG record中处理哪些磁盘块。
#define XLR_BKP_BLOCK_MASK 0x0E
设置XLR_BKP_BLOCK_MASK为0x0E,表示同时处理三个磁盘块
#define XLR_MAX_BKP_BLOCKS 3
一个XLOG record最多可以处理的磁盘块数
#define XLR_SET_BKP_BLOCK(iblk) (0x08 >> (iblk))
这个函数用于设置标志位的值,参数iblk用于表明0x08右移的位数
#define XLR_BKP_BLOCK_1 XLR_SET_BKP_BLOCK(0) /* 0x08 */
调用XLR_SET_BKP_BLOCK(0),设置XLR_BKP_BLOCK_1为0x08。
表示处理第一个磁盘块
#define XLR_BKP_BLOCK_2 XLR_SET_BKP_BLOCK(1) /* 0x04 */
调用XLR_SET_BKP_BLOCK(1),设置XLR_BKP_BLOCK_1为0x04。
表示处理第二个磁盘块
#define XLR_BKP_BLOCK_3 XLR_SET_BKP_BLOCK(2) /* 0x02 */
调用XLR_SET_BKP_BLOCK(2),设置XLR_BKP_BLOCK_1为0x02。
表示处理第三个磁盘块
一个XLOG record最多可以同时处理三个磁盘块,通过将上述宏定义参数与XLOG record中的xl_info进行位运算,可以对单个磁盘块进行操作。
(2) XLOG记录体的结构:
存在于XLOG.H文件中
typedef struct XLogRecData
{
Buffer buffer; 标识数据存在哪个缓冲区
char *data; 数据字符串
uint32 len; 数据长度
struct XLogRecData *next; 指向下一个数据的指针
} XLogRecData;
说明:需要注意记录体的构成,通常情况其是一个数据链,链中基本结构为:
Fixed-size header (XLogRecord struct,记录头)
rmgr-specific data(资源数据,对应操作的对象,如元组的id等内容)
BkpBlock
backup block data(操作的一些数据,如更新元组时,则可能是要更新的新值等)
BkpBlock
backup block data
XlogRecord是一条XLOG记录的头部信息,后面接着的是XLOG记录的数据XlogRecData。它们共同组成一条XLOG记录。