一、wal文件的介绍

1.什么是wal日志

wal文件是'write ahead log'的简称,又叫预写式日志,可以理解为先记录之后再操作,就是数据库的重做日志,用于在数据库系统重保证事物的持久性,wal日志记录了所有会改变数据文件的数据修改操作,在数据库发生故障时,可用通过重放wal日志来恢复到故障前的一个一致性状态。与oracle的redo log的功能是一样的,主要用于数据库恢复


2.wal日志的存放位置

cd $PGDATA/pg_wal 放在$PGDATA/pg_wal下面存放


3.wal日志段文件名的含义

3.1 wal日志文件名由24为字母数字长度组成,也叫lsn,默认情况下wal日志文件的大小为16M,wal日志的命名规则由3个部分组成,每部分包含8位,分别为日志时间线(timeline),日志序列号(logid)和logseg

日志的时间线:日志的时间线是从1开始递增,没发生过一次数据恢复就会发生一次变化,通过时间线可以知道数据库做过多少次的恢复

日志序列号:日志的序列号是从0开始递增,日志序列号(logid)和logseg的变化相关联,当logseg的最后两位为FF(256)还继续增长时,会在日志序列号(logid)会增加1,通过logid和logseg可以知道日志总共覆盖循环了多少次

logseg:16进制,最大只能是256,换成16进制即为FF


Postgresql的wal日志篇_数据

4.如何判断那个wal文件是当前正在使用的wal文件

查看当前使用的wal文件,不是最大序列号就代表正在使用的wal文件,而是通过一下命令进行查看

select pg_walfile_name('select pg_current_wal_lsn()');

5.wal日志记录的内容是主要有三类数据组成

一类是backup_block记录的数据块,

一类是数据的事物变化,事物的日志,如DML,DDL等数据变化的语句

一类是记录了checkpoint检查点的信息,但是checkpoint也会记录到PG的控制文件当中。


6.PG数据库wal日志如何进行写操作

Postgresql的wal日志篇_检查点_02

写的步骤

1.1 首先将事物写到wal缓冲区,由专门的wal write写进程进行写

1.2事物提交之后,然后将缓冲区的的数据记录到wal日志

wal write进程写的时机:

1.at commit 事物提交的时候

2.when wal buffer pool 当wal日志缓冲区满的时候

3.writes periodically 数据缓冲区的脏块写入数据文件之前



wal日志为什么要先记后写

Postgresql的wal日志篇_数据库_03

当一个事物执行了一个update的操作的时候,buffer cache会到磁盘拿取数据进行修改,然后进行提交,提交之后,wal buffer会立马将已经提交的事物写入到wal日志中,对数据进行了持久化。buffer cache中的保存中的数据为了减少IO,刷盘进制没那么频繁,buffer cache和wal buffer的刷盘机制存在时间差,如果实例突然发生崩溃,可以通过wal日志的数据进行数据恢复。

在进行commit操作的时候,wal buffer会将数据写入到wal日志中,但buffer cache不会将数据写入到数据文件中,数据缓冲区的写操作和事物提交的动作没有关系。数据缓冲区写的时候是批量的写,主要目的是为了减少IO

进行事物提交的时候也会造成io频繁,但是写的事物,数据量少,写的不是数据块。


7.checkpoint和wal日志的关系

Postgresql的wal日志篇_数据库_04

检查点是一种数据事件,当发生检查点时,就会将脏数据全部刷新到磁盘中,让数据持久化,checkpoint发生的越频繁,在数据库实例宕机后重放的wal日志量就越少,发生宕机时间点越靠近最后的检查点,重做的日志量也就越少。


8.数据库实例恢复与检查点和wal日志的关系

Postgresql的wal日志篇_检查点_05

1.首先会到控制文件,控制文件记录了当前的检查点的位置

2.找到检查点的位置之后会到wal日志去匹配检查点,然后找到对应的redo point

3.找到redo point之后会将记录的事物读取出来重新回放一遍进行数据恢复


9.利用wal日志进行数据恢复的步骤

Postgresql的wal日志篇_检查点_06

1.把数据库的数据读入到数据缓冲区

2.然后将事物种记录的操作重新执行一遍,利用wal日志重构数据


10.wal文件的管理

首先说一下oracle的redo log日志的机制是循环使用机制,通过日志组进行循环使用,假设日志组的有三个redo日志,第1个写满之后,会写第2个,第2个写满之后,会写第3个,第3个写满之后会覆盖第1个重复使用日志。

Postgresql的wal日志篇_数据_07

10.1 pg的wal日志写的机制分为两种

Postgresql的wal日志篇_数据_08

第一种机制:当第1个wal日志写满之后,会发生日志切换,切换到第2个日志,当第2个日志写满之后,会继续切换日志,切换到第3个wal日志,当所有的wal日志都写满了之后,会创建新的wal日志进行写操作

第二种机制:假设用过的wal日志已经用过了,现在不需要使用了,PG会将wal日志删掉或者改名给新的使用。

pg默认的是第二种机制,postgres的循环覆盖写是通过把旧的wal日志‘重命名’来实现,发生一次checkpoint之后,此checkpoint点之前的wal日志文件都可以删除,但postgres不会将其删除,而是‘重命名’旧的wal文件使之成为一个新的wal文件。所以wal文件目录下文件序列号最大的那个wal文件并不是正在写的wal文件,因为这个wal文件目录有可能是前1次checkpoint是重命名旧文件产生的。

10.2 wal日志的回收机制

PG判断wal日志是否可以回收,要看检查点的redo point位置,如果在redo point之前的wal日志,判断为不会影响实例恢复,可以进行回收。


10.3 wal日志满足以下条件时会发生切换

1.当wal日志写满的时候会自动发生切换

2.手动执行切换函数的时候会发生切换

select pg_switch_wal();

3.archive_mode is enabled and the time set to archive_timeout has been exceeded

基于主备复制需求强制发生切换



10.4 wal日志常用参数

checkpoint_completion_target

wal_keep_segments 保留wal日志的个数,

max_wal_size wal文件保留最大的尺寸,默认1024MB

wal_keep_size 用于指定pg_wal目录下要保留的wal日志的最少尺寸,主要是用于从节点接收这些WAL日志用于流复制

wal_segment_size wal文件最大可用尺寸,默认16MB,日志切换台频繁可以改变这个参数

wal_buffer 设置wal缓冲区尺寸,默认512KB,如果业务繁忙,可以稍微设置大一点,一般情况下1M或者2M就够了 wal缓存区设置太大也没意义,因为将数据记录到wal日志中,缓冲区的大小就会被释放。

10.5连续归档日志

连续归档是在wal段切换时将wal段文件复制到归档区域的功能,由archive(后台)进程执行

数据库如何进行归档:%p是wal文件的位置,%f代表保留原来wal文件的属性

默认情况下,归档日志的文件和wal日志的归档文件是一模一样的

alter system set archive_command = 'cp %p /home/postgres/archives/%f'

alter system set archive_mode = on; 设置数据库为归档模式


10.6wal文件调优相关

生产环境会经常在业务高峰期的时候会频繁的发生wal日志切换,频繁的wal日志切换会创建新的wal日志,如果wal日志切换的很频繁,会造成大量的IO,在调优的时候可以将wal日志的大小设置的大一点,让wal日志切换的频率不那么快。