PostgreSQL的存储系统二:REDOLOG文件存储结构

前端之家收集整理的这篇文章主要介绍了PostgreSQL的存储系统二:REDOLOG文件存储结构前端之家小编觉得挺不错的,现在分享给大家,也给大家做个参考。

Pg XLOG文件(常说的REDOLOG)名字的命名方法是在XLogFileName宏里定义的,分别由时间线ID、日志ID、段ID的八位16进制数依次构成。例如00000001000000010000008F。

#define@H_502_11@ XLogFileName(fname,tli,log,seg) \

@H_502_11@ snprintf(fname,MAXFNAMELEN,"%08X%08X%08X"@H_502_11@,seg)

不同的段ID对应不同的物理XLOG日志文件,日志ID是逻辑概念,有多个物理XLOG日志文件组成。

Pg XLOG文件(常说的REDOLOG)的大小初始值是在configure.in和configure文件里设置的,默认大小是16M。大小设置形式如下

@H_502_11@wal_segsize=16

@H_502_11@XLOG_SEG_SIZE (${wal_segsize} * 1024 * 1024)=16M

这个XLOG_SEG_SIZE是XLOG日志文件的段大小,就是一个物理的日志文件的大小。一个逻辑的XLOG日志文件大小是4Gb。

Pg XLOG文件的存储格式大致如下:

<@H_502_11@PageHeaderData>

<XLogRecord>

<rmgr-specific data>

<BkpBlock>

<XLogRecData>里面包括<CheckPoint>等

<BkpBlock>

<XLogRecData>

<BkpBlock>

<XLogRecData>

……

1

先看<@H_502_11@PageHeaderData>,这个根据不同情况对应@H_502_11@XLogLongPageHeaderData@H_502_11@XLogPageHeaderData结构。@H_502_11@XLOG@H_502_11@文件头用@H_502_11@XLogLongPageHeaderData@H_502_11@结构和一些合适场合,@H_502_11@XLogPageHeaderData@H_502_11@用在文件里的页面头。结构@H_502_11@XLogLongPageHeaderData@H_502_11@的第一个成员是结构@H_502_11@XLogPageHeaderData@H_502_11@。下面是这两个结构定义:

typedefstruct@H_502_11@ XLogLongPageHeaderData

@H_502_11@{

@H_502_11@ XLogPageHeaderDatastd@H_502_11@; /*页头结构*/

@H_502_11@ uint64 xlp_sysid@H_502_11@; /* 控制文件pg_control里的系统标识符*/

@H_502_11@ uint32@H_502_11@ xlp_seg_size@H_502_11@; /* XLOG文件大小 */

@H_502_11@ uint32@H_502_11@ xlp_xlog_blcksz@H_502_11@; /* XLOG文件页面大小 */

@H_502_11@} XLogLongPageHeaderData@H_502_11@;

XLOG文件里的页面头结构

typedefstruct@H_502_11@ XLogPageHeaderData

@H_502_11@{

@H_502_11@ uint16@H_502_11@ xlp_magic@H_502_11@; /* WAL版本指示器 */

@H_502_11@ uint16@H_502_11@ xlp_info@H_502_11@; /* flag bits,see below */

@H_502_11@ TimeLineIDxlp_tli@H_502_11@; /* 本页第一个记录的时间线*/

@H_502_11@ XLogRecPtrxlp_pageaddr@H_502_11@; /* 本页XLOG位置*/

@H_502_11@} XLogPageHeaderData@H_502_11@;

@H_502_11@ XLOG文件里的页面头结构@H_502_11@XLogPageHeaderData@H_502_11@的成员xlp_magic@H_502_11@表示@H_502_11@WAL@H_502_11@版本号。成员xlp_tli@H_502_11@表示本页第一个记录的时间线,成员xlp_pageaddr@H_502_11@表示本页的@H_502_11@XLOG@H_502_11@位置。成员xlp_info@H_502_11@表示紧跟页头的记录是否是跨页记录的一部分,或者该页头结构@H_502_11@XLogPageHeaderData@H_502_11@是否在文件头结构@H_502_11@XLogLongPageHeaderData@H_502_11@里。其值定义见下面:

当记录跨页时,在后面的页头里设置标志

#define@H_502_11@XLP_FIRST_IS_CONTRECORD 0x0001

这个指明是长页头(多用于文件第一页)

#define@H_502_11@ XLP_LONG_HEADER 0x0002

在xlp_info中定义的所有标志位(用于头的有效性检查)

#define@H_502_11@ XLP_ALL_FLAGS 0x0003

如果成员xlp_info的值是@H_502_11@XLP_FIRST_IS_CONTRECORD,表示页头后面跟的是一个跨页结构的一部分。

XLOG文件头结构@H_502_11@XLogLongPageHeaderData@H_502_11@的成员xlp_seg_size@H_502_11@表示@H_502_11@XLOG@H_502_11@文件大小,默认是@H_502_11@16M@H_502_11@。在configure.in和configure文件里设置形式如下

@H_502_11@wal_segsize=16

@H_502_11@XLOG_SEG_SIZE (${wal_segsize} * 1024 * 1024)=16M

成员xlp_xlog_blcksz表示文件里的页面大小,默认是8k。

2

<XLogRecord>根据情况不同,可能是XLogRecord或XLogContRecord结构,只有在上一个页面最后一个记录是跨页的情况下,页面头的记录前面才用XLogContRecord结构,表示该记录不是一个新记录,而是上一个记录的一部分。XLogRecord结构代表一个新的XLOG/REDOLOG记录,其后跟着实际的XLOG数据,XLogRecord结构定义如下:

typedefstruct@H_502_11@ XLogRecord

@H_502_11@{

@H_502_11@ pg_crc32@H_502_11@ xl_crc@H_502_11@; /* 该记录的CRC */

@H_502_11@ XLogRecPtrxl_prev@H_502_11@; /* xlog里前一个XLogRecord的指针*/

@H_502_11@ TransactionIdxl_xid@H_502_11@; /* 该记录事务ID */

@H_502_11@ uint32@H_502_11@ xl_tot_len@H_502_11@; /* 整个记录长度 */

@H_502_11@ uint32@H_502_11@ xl_len@H_502_11@; /* XLOG资源管理器数据长度 */

@H_502_11@ uint8@H_502_11@ xl_info@H_502_11@; /* 标志位 */

@H_502_11@ RmgrId@H_502_11@ xl_rmid@H_502_11@; /* 本记录的资源管理器ID */

@H_502_11@} XLogRecord@H_502_11@;

XLOG资源管理器时,其成员xl_info值可以是:

#define@H_502_11@ XLOG_CHECKPOINT_SHUTDOWN 0x00

#define@H_502_11@XLOG_CHECKPOINT_ONLINE 0x10

#define@H_502_11@ XLOG_NOOP 0x20

#define@H_502_11@ XLOG_NEXTOID 0x30

#define@H_502_11@ XLOG_SWITCH 0x40

#define@H_502_11@ XLOG_BACKUP_END 0x50

#define@H_502_11@XLOG_PARAMETER_CHANGE 0x60

#define@H_502_11@ XLOG_RESTORE_POINT 0x70

XACT资源管理器时,其成员xl_info高4位储存如下信息:

#define@H_502_11@ XLOG_XACT_COMMIT 0x00

#define@H_502_11@ XLOG_XACT_PREPARE 0x10

#define@H_502_11@ XLOG_XACT_ABORT 0x20

#define@H_502_11@XLOG_XACT_COMMIT_PREPARED 0x30

#define@H_502_11@XLOG_XACT_ABORT_PREPARED 0x40

#define@H_502_11@XLOG_XACT_ASSIGNMENT 0x50

XLOG仅使用xl_info的低4位,高4为由资源管理器rmgr使用

#define@H_502_11@ XLR_INFO_MASK 0x0F

如果用XLOG记录备份任一磁盘块(数据文件块吧),用其成员xl_info标志位记录,支持每个XLOG记录3个磁盘块的备份,使用xl_info标志的低1、2、3位

#define@H_502_11@ XLR_BKP_BLOCK_1 XLR_SET_BKP_BLOCK(0) /* 0x08 */

#define@H_502_11@ XLR_BKP_BLOCK_2 XLR_SET_BKP_BLOCK(1) /* 0x04 */

#define@H_502_11@ XLR_BKP_BLOCK_3 XLR_SET_BKP_BLOCK(2) /* 0x02 */

如果已备份块能从XLOG的压缩版本中被安全删除,设置Xl_info的0位(这就是,备份它们仅是为了防止写部分页partial-page-write)问题,并且不保证PITR恢复的一致性)。压缩算法将需要从这些块中解析出数据以创建一个相同的非全页XLOG记录。

#define@H_502_11@ XLR_BKP_REMOVABLE 0x01

成员xl_rmid记录资源管理器ID,就是资源种类ID,资源管理器的资源种类包括如下16种(不包含最后一个RM_MAX_ID,这个只是记录最大资源种类数):

#define@H_502_11@ RM_XLOG_ID 0

#define@H_502_11@ RM_XACT_ID 1

#define@H_502_11@ RM_SMGR_ID 2

#define@H_502_11@ RM_CLOG_ID 3

#define@H_502_11@ RM_DBASE_ID 4

#define@H_502_11@ RM_TBLSPC_ID 5

#define@H_502_11@ RM_MULTIXACT_ID 6

#define@H_502_11@ RM_RELMAP_ID 7

#define@H_502_11@ RM_STANDBY_ID 8

#define@H_502_11@ RM_HEAP2_ID 9

#define@H_502_11@ RM_HEAP_ID 10

#define@H_502_11@ RM_BTREE_ID 11

#define@H_502_11@ RM_HASH_ID 12

#define@H_502_11@ RM_GIN_ID 13

#define@H_502_11@ RM_GIST_ID 14

#define@H_502_11@ RM_SEQ_ID 15

#define@H_502_11@ RM_MAX_ID RM_SEQ_ID

当页头记录是跨页记录的一部分时,在@H_502_11@XLogLongPageHeaderData@H_502_11@结构的后面跟着@H_502_11@XLogContRecord@H_502_11@结构。原则@H_502_11@XLogRecord@H_502_11@记录头从不被分到多个页,如果页尾空间小于SizeOfXLogRecord,就弃之不用,直接使用下一个页面。如果在一个记录在一个页面没写完,在下一个页头的@H_502_11@XLogLongPageHeaderData@H_502_11@结构后面用@H_502_11@XLogContRecord@H_502_11@结构,此时@H_502_11@XLogLongPageHeaderData@H_502_11@结构的成员xlp_info@H_502_11@的值是@H_502_11@XLP_FIRST_IS_CONTRECORD@H_502_11@。

typedefstruct@H_502_11@ XLogContRecord

@H_502_11@{

@H_502_11@ uint32@H_502_11@ xl_rem_len@H_502_11@; /* 记录剩余数据总长度 */

@H_502_11@} XLogContRecord@H_502_11@;

3

<rmgr-specificdata>可能是事务状态定义等,例如结构xl_xact_commit、xl_xact_abort等

typedefstruct@H_502_11@ xl_xact_commit

@H_502_11@{

@H_502_11@ TimestampTzxact_time@H_502_11@; /* 提交时间 */

@H_502_11@ uint32@H_502_11@ xinfo@H_502_11@; /* 信息位 */

@H_502_11@ int@H_502_11@ nrels@H_502_11@; /* 关系文件 */

@H_502_11@ int@H_502_11@ nsubxacts@H_502_11@; /* 子事务XID */

@H_502_11@ int@H_502_11@ nmsgs@H_502_11@; /* 共享失效信息数 */

@H_502_11@ Oid@H_502_11@ dbId@H_502_11@; /* 数据库ID */

@H_502_11@ Oid@H_502_11@ tsId@H_502_11@; /* 数据库表空间ID */

@H_502_11@ /* 提交时要drop的关系文件节点数组*/

@H_502_11@ RelFileNodexnodes@H_502_11@[1]; /* 变长数组 */

@H_502_11@ /* 后面跟已提交子事务ID数组 */

@H_502_11@ /* 后面跟共享失效消息数组*/

@H_502_11@} xl_xact_commit@H_502_11@;

typedefstruct@H_502_11@ xl_xact_abort

@H_502_11@{

@H_502_11@ TimestampTzxact_time@H_502_11@; /* 退出时间 */

@H_502_11@ int@H_502_11@ nrels@H_502_11@; /* 关系文件节点数 */

@H_502_11@ int@H_502_11@ nsubxacts@H_502_11@; /* 子事务XID */

@H_502_11@ /* 退出时要drop的关系文件节点数组 */

@H_502_11@ RelFileNodexnodes@H_502_11@[1]; /*变长数组*/

@H_502_11@ /* 后面跟以退出的子事务XID数组 */

@H_502_11@} xl_xact_abort@H_502_11@;

@H_502_11@

@H_502_11@4

<BkpBlock>表示@H_502_11@BkpBlock结构,是@H_502_11@跟在@H_502_11@XLOG@H_502_11@记录@H_502_11@XLogRecord@H_502_11@后面的备份块头信息。XLOG代码知道PG数据页面中间常常包含一个无用的“洞”(“hole”——未使用的空间),其只包含值是0的字节。如果这个洞的长度大于0(hole_length >0),实际的跟在结构BkpBlock后面的块数据量是BLCKSZ -hole_length个字节

typedefstruct@H_502_11@ BkpBlock

@H_502_11@{

@H_502_11@ RelFileNodenode@H_502_11@; /* 包含该块的关系文件 */

@H_502_11@ ForkNumberfork@H_502_11@; /* 关系分支 */

@H_502_11@ BlockNumberblock@H_502_11@; /* 块数 */

@H_502_11@ uint16@H_502_11@ hole_offset@H_502_11@; /* "hole"前字节数 */

@H_502_11@ uint16@H_502_11@ hole_length@H_502_11@; /* "hole"的字节数 */

@H_502_11@ /* 实际的块数据跟在结构后面 */

@H_502_11@} BkpBlock@H_502_11@;

5

<XLogRecData>表示XLogRecData结构。要写入XLOG日志文件的资源管理器数据,由一或多个XLogRecData结构定义。

typedefstruct@H_502_11@ XLogRecData

@H_502_11@{

@H_502_11@ char@H_502_11@ *data@H_502_11@; /* 资源管理器包含数据的开始 */

@H_502_11@ uint32@H_502_11@ len@H_502_11@; /* 资源管理器包含数据的长度 */

@H_502_11@ Buffer@H_502_11@ buffer@H_502_11@; /* 有相应数据的buffer,如果有的话 */

@H_502_11@ bool@H_502_11@ buffer_std@H_502_11@; /* buffer是否有标准pd_lower/pd_upper */

@H_502_11@ struct@H_502_11@ XLogRecData *next@H_502_11@; /* 链里的下一个结构 */

@H_502_11@} XLogRecData@H_502_11@;

pd_lower页面开始位置与未分配空间开头的字节偏移,pd_upper与未分配空间结尾的字节偏移,LSN:最后修改这个页面的 xlog 记录最后一个字节后面第一个字节。

XLogRecData结构里记录各种数据库操作数据,其中典型的,数据是一个检查点(CheckPoint struct)。根据XLogRecord的成员xl_rmid是否等于RM_XLOG_ID以及的成员xl_info是否等于XLOG_CHECKPOINT_SHUTDOWN或XLOG_CHECKPOINT_ONLINE来判定数据是检查点。检查点的定义见下面。

typedefstruct@H_502_11@ CheckPoint

@H_502_11@{

@H_502_11@ XLogRecPtrredo@H_502_11@; /*开始创建一个检查点时下一个XLOG记录的位置*/

@H_502_11@ TimeLineIDThisTimeLineID@H_502_11@; /*当前时间线*/

@H_502_11@ uint32@H_502_11@ nextXidEpoch@H_502_11@; /*下一个事务ID的高排序位 */

@H_502_11@ TransactionIdnextXid@H_502_11@; /* 下一个空闲事务ID */

@H_502_11@ Oid@H_502_11@ nextOid@H_502_11@; /* 下一个空闲OID */

@H_502_11@ MultiXactIdnextMulti@H_502_11@; /* 下一个空闲多事务ID */

@H_502_11@ MultiXactOffsetnextMultiOffset@H_502_11@; /* next free MultiXact offset */

@H_502_11@ TransactionIdoldestXid@H_502_11@; /* cluster-wide minimum datfrozenxid */

@H_502_11@ Oid@H_502_11@ oldestXidDB@H_502_11@; /* database with minimum datfrozenxid*/

@H_502_11@ pg_time_t@H_502_11@ time@H_502_11@; /* 检查点时间戳 */

@H_502_11@ /*

仍在运行的最早的事务IDXID)。只有在从一个在线检查点初始化热备模式时才需要,以使在GUC参数wal_levelhot_standby时我们不用为在线检查点计算运行最早的XID。否则设置为常量InvalidTransactionId

*/

@H_502_11@ TransactionIdoldestActiveXid@H_502_11@;

@H_502_11@} CheckPoint@H_502_11@;


------------

转载请著明出处,来自博客: blog.csdn.net/beiigang beigang.iteye.com

猜你在找的Postgre SQL相关文章