概括起来,XLOG日志分为多个XLOG逻辑日志文件,每个逻辑日志文件包含多个XLOG段文件,每个XLOG段文件包含多个XLOG日志页:
- 每个XLOG逻辑日志文件都有一个ID
- 实际XLOG被分为pg_xlog目录下多个大小为16MB的段文件
- 文件名由时间线TimeLineID(8位16进制)、逻辑日志文件号(8位16进制)和段文件ID(8位16进制)组成
- 每个段文件分为多个8KB的页(块)
- 每个页包含一个头部,头部信息之后才是真正的XLOG日志记录
其中,值得注意的是,每个XLOG段文件大小可以在编译时使用–with-wal-segsize参数来指定,每页的大小可以在编译的时使用–with-wal-blocksize参数来指定,接下来主要介绍XLOG日志每页的组织形式。
XLOG日志页的组织形式
在PostgreSQL中,XLOG日志页可以分为以下几部分:
组成部分 | 具体含义 |
---|---|
PageHeaderData | XLOG日志页面头部信息 |
XLogRecord | XLog日志记录的头部信息 |
Data of RMGR | 资源管理器的数据,长度xl_len |
Backup Block 0 | 备份数据块头部BkpBlock + 块大小的备份数据 |
Backup Block 1 | 备份数据块头部BkpBlock + 块大小的备份数据 |
Backup Block 2 | 备份数据块头部BkpBlock + 块大小的备份数据 |
Backup Block 3 | 备份数据块头部BkpBlock + 块大小的备份数据 |
XLOG日志页头部信息
每个XLOG日志页分为页面头部信息和日志记录,其头部信息XLogPageHeaderData结构如下:
typedef struct XLogPageHeaderData
{
uint16 xlp_magic; /* 校验位,用于识别不同的XLOG版本 */
uint16 xlp_info; /* flag bits, see below */
TimeLineID xlp_tli; /* 页面第一条记录的时间线 */
XLogRecPtr xlp_pageaddr; /* XLOG页面的首地址 */
uint32 xlp_rem_len; /* 前XLOG页面最后一条记录剩余的长度 */
} XLogPageHeaderData;
其中,xlp_info是标志位:
- 0x0001表示该页面包含一个跨页面的记录(上个页面的最后一条记录)
- 0x0002表示该页面为段文件的首个页面,头部是一个长头部
- 0x0004表示该页面备份数据块是可选的
如果当前的页面没有足够的空间来存储一个XLOG日志记录,系统允许将剩余的数据存储到下一个页面,但是XLog日志记录的头部信息,即后文中的XLogRecord是不允许分开存储到两个不同的页面的。
如果该页面为段文件的首个页面,除了上面的标准页面头部信息外,还增加一个长头部用来更精确地定位文件,即XLogLongPageHeaderData:
typedef struct XLogLongPageHeaderData
{
XLogPageHeaderData std; /* 标准页面头部信息 */
uint64 xlp_sysid; /* pg_control 中的系统标识符*/
uint32 xlp_seg_size; /* 段的尺寸 */
uint32 xlp_xlog_blcksz; /* 页(块)的尺寸*/
} XLogLongPageHeaderData;