wal檔案結構
PG使用無符号64bit整型(uint64)作為日志檔案的尋址空間,理論上來說,如果隻有一個日志檔案,那麼這個事務日志檔案的大小最大為2^64Bytes(即16M*1TB=16EB)。為了高效管理事務日志檔案,PG把日志檔案劃分為N個大小為16M(預設值)的WAL segment file.
總體結構如下圖所示:
wal segment files
00000001 00000000 00000001
WAL segment file檔案長度為24,由3部分組成,每個部分是8個16進制數字:
1.第1部分是TimeLineID,0x00000000 -> 0xFFFFFFFF
2.第2部分是邏輯檔案ID,0x00000000 -> 0xFFFFFFFF
中間6個16進制沒使用
3.第3部分是實體檔案ID,0x00 -> 0xFF
邏輯檔案ID占32bit,實體檔案ID占8bit,16M的檔案占24bit(16是2^4 + 1M是2^20),合計64bit.PG通過這三部分的組合,達到最大64bit的檔案尋址空間.
dump資料内容
000000010000000000000001檔案
邏輯id是0
實體id是01
pg_waldump -p ./ -s 0/01000000 -n 4
第一條xlog
len:106
lsn:0/01000028
頭占了2*16+8=40位元組,是以開始位置是028
prev 0/00000000
desc:CHECKPOINT_SHUTDOWN redo 0/1000028; tli 1; prev tli 1; fpw true; xid 0:3; oid 10000; multi 1; offset 0; oldest xid 3 in DB 1; oldest multi 1 in DB 1; oldest/newest commit timestamp xid: 0/0; oldest running xid 0; shutdown
第二條xlog
len:30
lsn:0/01000098
絕對位置相當于9*16+8=152
prev: 0/01000028
desc: NEXTOID 18192
資料内容
調試方法
postgres=# create table test(id int);
postgres=# select pg_current_wal_lsn();
pg_current_wal_lsn
--------------------
0/15DE5D8
(1 row)
postgres=# insert into test values(1);
INSERT 0 1
postgres=# insert into test values(21);
INSERT 0 1
postgres=# checkpoint;
CHECKPOINT
postgres=# select pg_current_wal_lsn();
pg_current_wal_lsn
--------------------
0/15DE788
(1 row)
pg_waldump -p ./ -s 0/15DE5D8 -e 0/15DE788
建立語句
rmgr: Heap
PostgreSQL内部将WAL日志歸類到20多種不同的資料總管。這條WAL記錄所屬資料總管為Heap,即堆表。除了Heap還有Btree,Transaction等。
len (rec/tot): 3/ 59
WAL記錄的總長度是59位元組,其中main data部分是59位元組
tx: 556
事務号
lsn: 0/015DE5D8
本WAL記錄的LSN
prev 0/015DE5A0
上條WAL記錄的LSN
desc: INSERT+INIT off 1
這是一條insert類型的記錄(每個資料總管最多包含16種不同的WAL記錄類型),tuple在page中的位置為1。
blkref #0: rel 1663/16384/53523 blk 0
引用的第一個page所屬的對表檔案為1663/16384/53523,塊号為0(即ctid的前半部分)。通過oid2name可以查到是哪個堆表。
更新和删除語句
LSN
10的函數
select pg_current_wal_lsn(), pg_walfile_name(pg_current_wal_lsn()), pg_walfile_name_offset(pg_current_wal_lsn());
1代表檔案
5C7F00代表偏移,十進制就是6061824
9的函數
select pg_current_xlog_location(), pg_xlogfile_name(pg_current_xlog_location()), pg_xlogfile_name_offset(pg_current_xlog_location());