WAL 事务日志
什么是WAL
-
WAL是Write Ahead Logging的缩写,指的是将变更与行为写入事务日志的协议
-
在PostgreSQL中,事务日志/将行为写入事务日志的实现机制
-
在7.1版本中首次实现,是时间点恢复( Point-in-Time Recovery,PITR ) 与流复制(Streaming Replication,SR)实现的基础
WAL段文件
PG使用无符号64bit整型(uint64)作为事务日志文件的寻址空间.
为了便于管理,PG把事务日志文件划分为N个segment,每个segment称为WAL segment file,每个WAL segment file大小默认为16MB
可以在initdb时通过--wal-segsize选项来配置WAL段文件的大小。
WAL segment file文件名称为24个字符,由3部分组成,每个部分是8个字符,每个字符是一个16进制值(即0~F)
第1部分是TimeLineID,取值范围是0x00000000 -> 0xFFFFFFFF
第2部分是逻辑文件ID,取值范围是0x00000000 -> 0xFFFFFFFF
第3部分是物理文件ID,取值范围是0x00000000 -> 0x000000FF
LSN 标识符
为了标记每个数据页最后修改它的日志记录号,可以理解为XLOG Record在事务日志文件中的偏移
在每个数据页的PageHeaderData结构中引入了一个LSN标识符,指向最后修改页面的日志记录
typedef struct PageHeaderData { /* XXX LSN is member of *any* block, not only page-organized ones */ PageXLogRecPtr pd_lsn; /* LSN: next byte after last byte of xlog * record for last change to this page */ uint16 pd_checksum; /* checksum */ uint16 pd_flags; /* flag bits, see below */ LocationIndex pd_lower; /* offset to start of free space */ LocationIndex pd_upper; /* offset to end of free space */ LocationIndex pd_special; /* offset to start of special space */ uint16 pd_pagesize_version; TransactionId pd_prune_xid; /* oldest prunable XID, or zero if none */ ItemIdData pd_linp[FLEXIBLE_ARRAY_MEMBER]; /* line pointer array */ } PageHeaderData;
LSN由3部分组成,分别是逻辑文件ID,物理文件ID和文件内偏移,三者共同组成unit64(32+8+24),达到最大64bit的+文件寻址空间.
根据LSN号推算得到其对应的日志文件
WAL segment file内部结构
WAL segment file内部划分为N个page(Block),每个page大小为8192 Bytes即8K,每个WAL segment file第1个page的header在PG源码中相应的数据结构是XLogLongPageHeaderData,后续其他page的header对应的数据结构是XLogPageHeaderData,结构定义在src/include/access/xlog_internal.h中
在一个page中,page header之后是N个XLOG Record。
XLogLongPageHeaderData 与 XLogPageHeaderData 结构的定义在src/include/access/xlog_internal.h
XLOG记录的数据部分可以分为两类:备份区块(完整的页面)或非备份区块(不同的操作对应的数据不同)
WAL段切换
WAL段已经被填满。
pg_switch_wal()被调用。
启用了archive_mode,且已经超过archive_timeout配置的时间。
WAL段管理
切换后的段文件通常会被回收(重命名或重用)以供将来使用,如果不需要,也可能会被删除
配置参数wal_keep_segments及复制槽功能都会影响WAL段文件的数量。
使用pg_waldump查看WAL
postgres=# create table t_wal(n_id int); CREATE TABLE ztq=# select pg_current_wal_lsn(); pg_current_wal_lsn -------------------- 0/5C013238 (1 row) postgres=# insert into t_wal values(1); INSERT 0 1 postgres=# insert into t_wal values(2); INSERT 0 1 postgres=# checkpoint; CHECKPOINT postgres=# select pg_current_wal_lsn(); pg_current_wal_lsn -------------------- 0/5C013548 (1 row)
[postgres@evm-cgn20cgcho6hmrpkhv60 ~]$ pg_waldump -s 0/5C013238 -e 0/5C013548 rmgr: Heap len (rec/tot): 59/ 59, tx: 16195, lsn: 0/5C013238, prev 0/5C013200, desc: INSERT+INIT off 1 flags 0x00, blkref #0: rel 1663/16384/16852 blk 0 rmgr: Transaction len (rec/tot): 34/ 34, tx: 16195, lsn: 0/5C013278, prev 0/5C013238, desc: COMMIT 2023-05-15 16:01:27.400630 CST rmgr: Standby len (rec/tot): 54/ 54, tx: 0, lsn: 0/5C0132A0, prev 0/5C013278, desc: RUNNING_XACTS nextXid 16196 latestCompletedXid 16194 oldestRunningXid 16195; 1 xacts: 16195 rmgr: Heap len (rec/tot): 59/ 59, tx: 16196, lsn: 0/5C0132D8, prev 0/5C0132A0, desc: INSERT off 2 flags 0x00, blkref #0: rel 1663/16384/16852 blk 0 rmgr: Transaction len (rec/tot): 34/ 34, tx: 16196, lsn: 0/5C013318, prev 0/5C0132D8, desc: COMMIT 2023-05-15 16:01:36.487546 CST rmgr: Standby len (rec/tot): 50/ 50, tx: 0, lsn: 0/5C013340, prev 0/5C013318, desc: RUNNING_XACTS nextXid 16197 latestCompletedXid 16196 oldestRunningXid 16197 rmgr: Standby len (rec/tot): 50/ 50, tx: 0, lsn: 0/5C013378, prev 0/5C013340, desc: RUNNING_XACTS nextXid 16197 latestCompletedXid 16196 oldestRunningXid 16197 rmgr: XLOG len (rec/tot): 114/ 114, tx: 0, lsn: 0/5C0133B0, prev 0/5C013378, desc: CHECKPOINT_ONLINE redo 0/5C013378; tli 1; prev tli 1; fpw true; xid 0:16197; oid 25044; multi 1; offset 0; oldest xid 480 in DB 1; oldest multi 1 in DB 1; oldest/newest commit timestamp xid: 0/0; oldest running xid 16197; online rmgr: Standby len (rec/tot): 50/ 50, tx: 0, lsn: 0/5C013428, prev 0/5C0133B0, desc: RUNNING_XACTS nextXid 16197 latestCompletedXid 16196 oldestRunningXid 16197 rmgr: Standby len (rec/tot): 50/ 50, tx: 0, lsn: 0/5C013460, prev 0/5C013428, desc: RUNNING_XACTS nextXid 16197 latestCompletedXid 16196 oldestRunningXid 16197 rmgr: XLOG len (rec/tot): 114/ 114, tx: 0, lsn: 0/5C013498, prev 0/5C013460, desc: CHECKPOINT_ONLINE redo 0/5C013460; tli 1; prev tli 1; fpw true; xid 0:16197; oid 25044; multi 1; offset 0; oldest xid 480 in DB 1; oldest multi 1 in DB 1; oldest/newest commit timestamp xid: 0/0; oldest running xid 16197; online rmgr: Standby len (rec/tot): 50/ 50, tx: 0, lsn: 0/5C013510, prev 0/5C013498, desc: RUNNING_XACTS nextXid 16197 latestCompletedXid 16196 oldestRunningXid 16197
pg_waldump的组成部分
rmgr : 资源名称,也即日志的归类。
lsn: 日志编号
desc :对日志详细信息的描述