PostgreSQL中WAL segment file内部结构分析

70次阅读
没有评论

共计 4430 个字符,预计需要花费 12 分钟才能阅读完成。

本篇内容介绍了“PostgreSQL 中 WAL segment file 内部结构分析”的有关知识,在实际案例的操作过程中,不少人都会遇到这样的困境,接下来就让丸趣 TV 小编带领大家学习一下如何处理这些情况吧!希望大家仔细阅读,能够学有所成!

WAL segment file
WAL segment file 内部划分为 N 个 page(Block), 每个 page 大小为 8K, 第一个 page 的 header 对应的数据结构为 XLogLongPageHeaderData, 其他 page 的 header 对应的数据结构是 XLogPageHeaderData. 在 header 后是 N 个 XLOG Record.

XLOG Record
XLOG Record 由两部分组成, 第一部分固定大小, 对应的结构体为 XLogRecord; 第二部分是 XLOG Record data

XLOG Record data
XLOG Record data 由以下几部分组成:
1.0..N 个 XLogRecordBlockHeader, 每个 XLogRecordBlockHeader 对应一个 block data;
注意: 如设置了 BKPBLOCK_HAS_IMAGE 标记, 则在 XLogRecordBlockHeader 结构体后跟 XLogRecordBlockImageHeader 结构体; 如设置了 BKPIMAGE_HAS_HOLE 和 BKPIMAGE_IS_COMPRESSED 则在 XLogRecordBlockImageHeader 后跟 XLogRecordBlockCompressHeader 结构体;
2.XLogRecordDataHeader[Short|Long]: 如数据 256Bytes, 则使用 Short 格式, 否则使用 Long 格式;
3.block data:full-write-block 数据, 如启用了压缩, 则压缩存储, 相关元数据存储在 XLogRecordBlockHeader 中的 XLogRecordBlockCompressHeader 中.
4.main data:(tuple) data/checkpoint 等日志数据.

二、样例说明

使用 linux 下的 hexdump 工具查看 WAL 文件中的内容, 可以直观的感知上述内部结构
测试机的 WAL segmengt file:

[xdb@localhost pg_wal]$ ll
total 32796
-rw-------. 1 xdb xdb 16777216 Dec 18 10:52 000000010000000100000042
...

XLogPageHeaderData
uint16 xlp_magic

[xdb@localhost pg_wal]$ hexdump -C 000000010000000100000042 -s 0 -n 2
00000000 98 d0 |..|
00000002

magic value 为 0xD098.
注意:X86 CPU 使用小端模式(Little-Endian), 如数据占用超过 1 个字节, 则高位字节在内存高位地址, 低位字节在内存低位地址, 写入到文件时直接从内存 flush 到磁盘上, 磁盘文件上的字节顺序与内存保持一致.

uint16 xlp_info

[xdb@localhost pg_wal]$ hexdump -C 000000010000000100000042 -s 2 -n 2 
00000002 07 00 |..|
00000004

xlp_info 标志为 0x0007, 即 XLP_FIRST_IS_CONTRECORD | XLP_LONG_HEADER | XLP_BKP_REMOVABLE
标明:
1.XLOG Record 跨越 page 边界;
2. 这个 page 的 header 是 XLogLongPageHeaderData
3. 从该页起始的 backup blocks 是可选的(不一定存在)

TimeLineID(uint32) xlp_tli

[xdb@localhost pg_wal]$ hexdump -C 000000010000000100000042 -s 4 -n 4
00000004 01 00 00 00 |....|
00000008

TimeLineID 为 0x00000001, 即十进制数值 1

XLogRecPtr(uint64) xlp_pageaddr

[xdb@localhost pg_wal]$ hexdump -C 000000010000000100000042 -s 8 -n 8
00000008 00 00 00 42 01 00 00 00 |...B....|
00000010

XLog Record 在事务日志指针 (偏移) 为 0x00000001 42000000

uint32 xlp_rem_len

[xdb@localhost pg_wal]$ hexdump -C 000000010000000100000042 -s 16 -n 4
00000010 0f 00 00 00 |....|
00000014

上一页空间不足以存储 XLOG Record, 该 Record 在本页继续存储占用的空间大小:0x0000000F

XLogLongPageHeaderData
XLogLongPageHeaderData 的第一个域字段是 XLogPageHeaderData, 相关数据参见以上 XLogPageHeaderData 描述.
注意:XLogPageHeaderData 结构体按最大基本类型对齐, 会扩充为 24Bytes(原为 20Bytes), 因此 XLogLongPageHeaderData 的内容从 24 开始起算.

uint64 xlp_sysid

[xdb@localhost pg_wal]$ hexdump -C 000000010000000100000042 -s 24 -n 8
00000018 42 72 7f 55 41 76 ee 5b |Br.UAv.[|
00000020

系统标识码 0x5BEE7641557F7242

[xdb@localhost ~]$ echo $((0x5BEE7641557F7242))
6624362124887945794

使用 pg_controldata 查看 Database system identifier– 6624362124887945794

[xdb@localhost ~]$ pg_controldata
pg_control version number: 1100
Catalog version number: 201809051
Database system identifier: 6624362124887945794
...

uint32 xlp_seg_size

[xdb@localhost pg_wal]$ hexdump -C 000000010000000100000042 -s 32 -n 4
00000020 00 00 00 01 |....|
00000024

值为 0x01000000, 即 16M

[xdb@localhost ~]$ echo $((0x01000000))
16777216

uint32 xlp_xlog_blcksz

[xdb@localhost pg_wal]$ hexdump -C 000000010000000100000042 -s 36 -n 4
00000024 00 20 00 00 |. ..|
00000028

值为 0x00002000, 即 8K

[xdb@localhost ~]$ echo $((0x00002000))
8192

上一 page XLOG Record 的数据
由于空间不足, 上一 page 的 XLOG Record 在本页继续存储占用的数据(xlp_rem_len=0x0F, 补齐为 16B)

[xdb@localhost pg_wal]$ hexdump -C 000000010000000100000042 -s 40 -n 16
00000028 31 00 00 00 00 00 00 00 00 69 b8 40 25 00 00 00 |1........i.@%...|
00000038

XLogRecord
接下来是 XLogRecord
uint32 xl_tot_len

[xdb@localhost pg_wal]$ hexdump -C 000000010000000100000042 -s 56 -n 4
00000038 4f 00 00 00 |O...|
0000003c

XLOG Record 长度为 0x0000004F
TransactionId(uint32) xl_xid

[xdb@localhost pg_wal]$ hexdump -C 000000010000000100000042 -s 60 -n 4
0000003c 6b 07 00 00 |k...|
00000040

事务 ID 为 0x0000076B, 即十进制的 1899
XLogRecPtr(uint64) xl_prev

[xdb@localhost pg_wal]$ hexdump -C 000000010000000100000042 -s 64 -n 8
00000040 c0 ff ff 41 01 00 00 00 |...A....|
00000048

上一个 XLOG Record 的偏移, 即 0x00000001 41FFFFC0
unit8 xl_info

[xdb@localhost pg_wal]$ hexdump -C 000000010000000100000042 -s 72 -n 1
00000048 00 |.|
00000049

标志位为 0x00
unit8 xl_rmid

[xdb@localhost pg_wal]$ hexdump -C 000000010000000100000042 -s 73 -n 1
00000049 0a |.|
0000004a

该记录的资源管理器, 即 0x0A
2 bytes of padding

[xdb@localhost pg_wal]$ hexdump -C 000000010000000100000042 -s 74 -n 2
0000004a 00 00 |..|
0000004c

pg_crc32c(uint32) xl_crc

[xdb@localhost pg_wal]$ hexdump -C 000000010000000100000042 -s 76 -n 4
0000004c ea 21 d2 50 |.!.P|
00000050

CRC 校验位, 即 0x50D221EA

“PostgreSQL 中 WAL segment file 内部结构分析”的内容就介绍到这里了,感谢大家的阅读。如果想了解更多行业相关的知识可以关注丸趣 TV 网站,丸趣 TV 小编将为大家输出更多高质量的实用文章!

正文完
 
丸趣
版权声明:本站原创文章,由 丸趣 2023-07-24发表,共计4430字。
转载说明:除特殊说明外本站除技术相关以外文章皆由网络搜集发布,转载请注明出处。
评论(没有评论)