PostgreSQL DBA(16) - WAL segment file內部結構

husthxd發表於2018-12-18

上節介紹了WAL的檔案結構,PG把日誌檔案劃分為N個大小為16M(預設值)的WAL segment file,本節就WAL segment file的內部結構作一簡要概述。

一、WAL segment file內部結構

WAL segment file預設大小為16MB,其內部結構如下圖所示:


PostgreSQL DBA(16) - WAL segment file內部結構
WAL segment file內部結構

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

XLOG Record data下節再行介紹

三、參考資料

WAL Internals Of PostgreSQL
PostgreSQL 原始碼解讀(109)- WAL#5(相關資料結構)
關於結構體佔用空間大小總結

來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/6906/viewspace-2374777/,如需轉載,請註明出處,否則將追究法律責任。

相關文章