1 xlog
1.1 简介
在PG中,任何修改数据库的操作都会记录一份日志,这个日志就叫做xlog。在9.2.4版本中,xlog日志的目录是PGDATA/pg_xlog,在更高的版本里,该目录变成了$PGDATA/pg_wal

WAL(Write-Ahead Logging,预写日志)是一种用于确保数据库数据一致性和恢复能力的技术。XLOG 文件就是 WAL 的物理存储形式,它记录了所有修改数据库内容的操作,包括数据的插入、更新、删除以及元数据的变更等
wal_level参数影响wal日志的详细程度:
minimal:最低的日志级别,仅记录足以保证崩溃恢复的信息。
Replica:提供足够日志信息支持热备和流复制,记录所有事务的变更,包括索引变更和行版本信息
Logical:提供最详细的日志记录,包括所有逻辑变更
1.2 Xlog的大小
Wal由多个segment组成,而一个segment又是由多个page组成的,其大小定义在src/include/pg_config.h 中

默认大小:XLOG_BLCKSZ 8K:一次写入8K
XLOG_SEG_SIZE 16M:一个seg写满为16MB
只允许在编译的时候修改。
wal segment的大小由参数wal_block_size控制,编译之后无法修改



1.3 Xlog的初始化
对应于xlog,其初始化的入口函数是BootStrapXLOG,该函数只会在初始化的时候调用一次,主要用于创建pg_control文件和初始化第一个xlog segment。

Xlog的命名规则:
在PG10之前的版本中,由3个参数组成共24位的十六进制字符串,每个参数占8位。
三个参数分别为:tli、log、seg
-rw------- 1 postgres postgres 16777216 Jul 22 18:27 00000001000000000000003B
对应这个文件
Tli(完整名称是timeline:表示数据库的状态,在数据恢复后会发生变化):00000001
Log file ID:00000000
Segment:0000003B
而在PG10之后,Log file ID和segment合并为一个参数(Log_segment_number)
1.4 Xlog文件的作用
- 数据恢复
在系统崩溃或发生故障后,XLOG 文件可以用来恢复数据库到一致的状态。PostgreSQL 通过重放(replay)XLOG 中的记录来重建事务,确保数据的完整性。
- 复制
在流复制(streaming replication)中,XLOG 文件的内容会被发送到从服务器(standby server),以便从服务器可以同步主服务器(master server)的状态。
- 归档
XLOG 文件可以被归档(archiving),这样即使在磁盘空间有限的情况下,也可以保留一定时间的历史日志记录。
1.5 什么时候会产生新的xlog segment
- 当前的WAL段文件已满
当前的wal segment文件写满时,Postgresql会创建新的segment文件,默认大小是16MB
- 检查点
检查点期间,会强制将内存中的数据写入磁盘,并生成新的segment文件。
检查点的触发条件包括:
时间间隔:默认情况下,检查点每5min触发一次(checkpoint_timeout)
WAL文件大小:当wal文件的大小达到一定阈值时,也会触发检查点
手动触发:checkpoint命令
置换脏页(隐性条件):内存中置换脏页也会触发检查点
- Wal日志切换
select pg_switch_wal();
1.6 什么样的wal segment会被清理
1.在开启归档archive_mode=on的情况下:归档成功(.done)的wal segment会被删除。
2.在有复制槽的情况下,当所有复制槽的restart_lsn已经超过了当前wal_segment的lsn,那么该wal会被删除。
3.检查点触发,确定该segment不被任何事务或恢复操作需要
4.流复制:与参数synchronous_commit有关
- off:事务提交不需要等待任何确认,即不等待WAL记录被写入磁盘或备库。
- local:事务提交需要等待WAL记录被写入本地磁盘。
- remote_write:事务提交需要等待WAL记录被写入至少一个备库的磁盘。
- remote_apply:事务提交需要等待WAL记录被至少一个备库接收并应用。
- on:等同于 remote_write,事务提交需要等待WAL记录被至少一个备库写入磁盘。
1.7 wal segment的自动清理的时机
检查点会触发WAL段文件的清理
1.8 wal segment的保留受什么参数影响
wal日志的保留受多个参数影响:
- archive_mode:控制是否开启WAL归档。当设置为on或always时,会触发archive_command进行WAL文件的归档操作。
- archive_command:指定将WAL复制到外部介质的Shell命令。如果命令返回非0,PostgreSQL会无限重试,导致WAL堆积。
- archive_timeout:当某个segment最后一次写入距今超过该秒数时强制切换WAL,防止低负载下WAL长时间不归档,但会增加文件数量。
- max_wal_size:WAL目录软上限。当WAL累积超过该值时,强制触发checkpoint,期望通过回收/删除降低大小。
- min_wal_size:WAL目录软下限。一次checkpoint结束后,PostgreSQL会尝试将WAL大小收缩到不低于该值。
- wal_keep_segments:即使归档/复制均已完成,也必须在pg_wal中保留最近N个segment。
- max_slot_wal_keep_size:在PostgreSQL 13及以上版本中,用于控制复制槽保留的最大日志量。
- wal_keep_size:在PostgreSQL 13及以上版本中,以MB定义的替代wal_keep_segments,同样属于硬约束窗口。
- checkpoint_timeout:两次checkpoint最长间隔。间隔越长,WAL越多;但过短会导致I/O抖动。
- checkpoint_completion_target:checkpoint持续时间占间隔比例。较大值可平滑I/O,降低WAL峰值。
2 归档xlog
2.1为什么要归档
将wal日志移动到一个安全的位置。
通过合理配置和管理wal归档,可以显著提高数据库的可靠性和安全性。
pg_wal/archive_status/下的文件表示对应wal的归档状态:
.done:表示已经归档
.ready:表示可以进行归档,归档完成后,.ready会变为.done
这些文件都没有内容,只是个空文件
2.2什么时候触发归档
产生新的wal segment
达到archive_timeout参数设置的超时时间
检查点触发:会将内存中的数据写入磁盘,可能因此产生新的wal segment
2.3归档日志的清理
归档目录的xlog文件的自动清理主要依赖于参数archive_cleanup_command的配置,在每次wal segment成功归档后自动执行,清理不再需要的旧日志文件。
具体哪些文件会被清理,要看archive_cleanup_command的具体配置。
若未配置以上参数,则需要在操作系统层面设置定时任务来清理。
若两者都未配置,则归档目录下的xlog会不断堆积。
3 Xlog内容解析
从xlog文件中可以获取如下信息:
- 操作对象:索引还是表
- 记录长度
- 事务编号
- Lsn
- 操作类型:增、删、改
- 实际操作对象
举例:
下面是使用pg_waldump解析一个xlog文件后得到的结果
pg_waldump 000000xxxxxxx

下面是对每一行输出的解释:
rmgr:B-tree | 表示这个记录是由B-Tree索引管理器生成的 |
rmgr: Heap | 表示这条记录是由Heap表管理器生成的。 Heap表示操作对象是表、而B-Tree表示操作对象是索引。 |
len (rec/tot): 64/64 | 表示这个记录的长度是64字节,总共也是64字节 |
tx: | 表示事务编号 |
lsn | 表示这条记录的日志序列号 |
prev | 表示这条记录的前一条记录的LSN |
desc | 描述了这个记录的操作类型。 INSERT_LEAF off 324表示在B-Tree的叶子节点上执行了一个INSERT操作,偏移量是324 |
blkref | 表示这个操作涉及到的关系或者索引的oid,以及对应的块号 |
有了以上的信息,主要是有了desc和oid,我们就能够具体到数据库的某一张表上的具体操作。
4 流复制和复制槽
4.1 流复制
流复制是一种机制,主库将wal实时发送到从库,实时同步
从库通过pg_basebackup或其他工具从主库获取初始备份,通过postgresql.conf连接到主库,实时接收WAL并应用
4.2 复制槽
主备通过复制槽接收和推送wal日志,有一定延迟
Comments NOTHING