Postgresql WAL日志浅析 您所在的位置:网站首页 wal是什么缩写 Postgresql WAL日志浅析

Postgresql WAL日志浅析

#Postgresql WAL日志浅析| 来源: 网络整理| 查看: 265

一、预写日志(WAL)

预写式日志(Write Ahead Log,WAL)是保证数据完整性的一种标准方法。简单来说,WAL的中心概念是数据文件(存储着表和索引)的修改必须在这些动作被日志记录之后才被写入,即在描述这些改变的日志记录被刷到持久存储以后。如果我们遵循这种过程,我们不需要在每个事务提交时刷写数据页面到磁盘,因为我们知道在发生崩溃时可以使用日志来恢复数据库:任何还没有被应用到数据页面的改变可以根据其日志记录重做(这是前滚恢复,也被称为REDO)。使用WAL可以显著降低磁盘的写次数,因为只有日志文件需要被刷出到磁盘以保证事务被提交,而被事务改变的每一个数据文件则不必被刷出。日志文件被按照顺序写入,因此同步日志的代价要远低于刷写数据页面的代价。在处理很多影响数据存储不同部分的小事务的服务器上这一点尤其明显。此外,当服务器在处理很多小的并行事务时,日志文件的一个fsync可以提交很多事务。关闭 fsync 对 SELECT 无影响, 而 UPDATE 性能有较大提升,这个场景提升了 111%;当然关闭 fsync 参数的代价是巨大的,当数据库主机遭受操作系统故障或硬件故障时,数据库很有可能无法启动,并丢失数据,建议生产库不要关闭这参数。WAL也使得在线备份和时间点恢复能被支持。通过归档WAL数据,我们可以支持回转到被可用WAL数据覆盖的任何时间:我们简单地安装数据库的一个较早的物理备份,并且重放WAL日志一直到所期望的时间。另外,该物理备份不需要是数据库状态的一个一致的快照 — 如果它的制作经过了一段时间,则重放这一段时间的WAL日志将会修复任何内部不一致性。

二、简介

类似于Oracle的redo,PostgreSQL的redo文件被称为WAL文件或XLOG文件,存放在 $PGDATA/pg_xlog或 $PGDATA/pg_wal目录中(PostgreSQL从10版本开始,将所用xlog相关的全部用wal替换了)。任何试图修改数据库数据的操作都会写一份日志到磁盘。wal命名格式文件名称为16进制的24个字符组成,每8个字符一组,每组的意义如下:

 

 通过select pg_switch_xlog()或select pg_switch_wal();可以切换xlog/wal日志。

wal日志即write ahead log预写式日志,简称wal日志。wal日志可以说是PostgreSQL中十分重要的部分,相当于oracle中的redo日志。 当数据库中数据发生变更时: change发生时:先要将变更后内容计入wal buffer中,再将变更后的数据写入data buffer; commit发生时:wal buffer中数据刷新到磁盘; checkpoint发生时:将所有data buffer刷新的磁盘。如果没有wal日志,那么数据库中将会发生什么? 首先,当我们在数据库中更新数据时,如果没有wal日志,那么每次更新都会将数据刷到磁盘上,并且这个动作是随机i/o,性能可想而知。并且没有wal日志,关系型数据库中事务的ACID如何保证呢? 因此wal日志重要性可想而知。其中心思想就是:先写入日志文件,再写入数据。说到checkpoint,我们再来看看哪些情况会触发数据库的checkpoing: 1.手动执行CHECKPOINT命令; 2.执行需要检查点的命令(例如pg_start_backup 或pg_ctl stop|restart等等); 3.达到检查点配置时间(checkpoint_timeout); 4.max_wal_size已满。checkpoint_timeout: 自动 WAL 检查点之间的最长时间,以秒计。合理的范围在 30 秒到 1 天之间。默认是 5 分钟(5min)。增加这个参数的值会增加崩溃恢复所需的时间。

max_wal_size: 在自动 WAL检查点之间允许WAL 增长到的最大尺寸。这是一个软限制,在特殊的情况 下 WAL 尺寸可能会超过max_wal_size, 例如在重度负荷下、archive_command失败或者高的 wal_keep_segments设置。默认为 1 GB。增加这个参数可能导致崩溃恢复所需的时间。( wal_keep_segments用于指定pg_wal目录中保存的过去的wal文件(wal 段)的最小数量,以防备用服务器在进行流复制时需要。)和max_wal_size相对应的还有个min_wal_size,只要 WAL 磁盘用量保持在这个设置之下,在检查点时旧的 WAL文件总是被回收以便未来使用,而不是直接被删除。

wal切换步骤是这样的:单个wal日志写满(默认大小16MB,编译数据库时指定)继续写下一个wal日志,直到磁盘剩余空间不足min_wal_size时才会将旧的 WAL文件回收以便继续使用。但是这种模式有一个弊端就是如果在checkpoint之前产生了大量的wal日志就会导致发生checkpoint时对性能的影响巨大,因此pg中还有一个参数checkpoint_completion_target 来进行调整。checkpoint_completion_target: 指定检查点完成的目标,作为检查点之间总时间的一部分。默认是 0.5。假如我的checkpoint_timeout设置是30分钟,而wal生成了10G,那么设置成0.5就允许我在15分钟内完成checkpoint,调大这个值就可以降低checkpoint对性能的影响,但是万一数据库出现故障,那么这个值设置越大数据就越危险。总结:大多数检查点应该是基于时间的,即由checkpoint_timeout触发。 性能(不频繁检查点)与恢复所需时间(频繁检查点)之间需要抉择: 值在15-30分钟之间是比例合适的,但到1小时不是什么坏事。 在决定checkpoint_timeout后,通过估计WAL的数量选择max_wal_size。 设置checkpoint_completion_target以便内核将数据刷新到磁盘的时间足够(但不是太多)

三、切换WAL日志

pg_switch_wal()或pg_switch_xlog()强制服务器切换到一个新的预写式日志文件,这允许对当前文件进行归档(假设你正在使用连续归档)。 其结果是在刚刚完成的预写式日志文件中结束预写式日志位置加1。 如果自从上次预写式日志切换以来没有提前写日志活动,pg_switch_wal将不做任何操作,并返回当前正在使用的提前写日志文件的起始位置。默认情况下该函数仅限超级用户使用,但可以授权其他用户执行该函数。pg_switch_xlog()用于PG 10之前,从PG 10开始切换归档日志使用pg_switch_wal()。PG也提供了相应的函数根据LSN获取日志文件名:

 

 四、配置WAL归档

 

 必须重启,如果开启了归档,则在归档路径下的archive_status目录里,会有类似000000010000000000000002.ready和000000010000000000000003.done的文件,.ready表示XLOG文件已写满,可以调用归档命令了,.done表示已归档完成。开启了归档后,只有归档成功的pg_xlog文件才会被清除。在每次归档命令被执行后,会触发清除标签的动作,在执行检查点时,也会触发清除归档标签文件的动作。

五、自动清理WAL日志

一般来说,设置自动清理archive_log 可以在配置文件中添加archive_cleanup_command = 'pg_archivecleanup archivelocation %r'

 

或者:alter system set archive_cleanup_command='pg_archivecleanup /var/lib/postgresql/data/pg_wal %r';

 六、手动清理WAL日志

如果配置了archive_mode=on,但是没有配置archive_command,那么xlog文件会一直堆积(xlog写完后,会写.ready,但是由于没有配置archive_command,也就是说不会触发归档命令,所以一直都不会写 .done),所以xlog会一直不清理。1、读取控制文件,找到能清理的xlog范围

 

 其中,“Latest checkpoint's REDO WAL file: 000000010000000000000005”之前的文件都可以清理。

2、通过pg_archivecleanup清理

pg_archivecleanup -d $PGDATA/pg_wal 000000010000000000000005

pg的wal日志保存在数据库目录下的pg_wal/子目录,这个日志存在的目的是为了保证崩溃后的安全,如果系统崩溃,可以“重放”从最后一次检查点以来的日志项来恢复数据库的一致性。但是也存在日志膨胀的问题,

七、WAL归档

在生产环境,为了保证数据高可用性,通常需要设置归档,所谓的归档,其实就是把pg_wal里面的日志备份出来,当系统故障后可以通过归档的日志文件对数据进行恢复:

配置归档需要开启如下参数:

1、wal_level = replica (pg13默认已经开启replica) 该参数的可选的值有minimal,replica和logical,wal的级别依次增高,在wal的信息也越多。由于minimal这一级别的wal不包含从基础的备份和wal日志重建数据的足够信息,在该模式下,无法开启wal日志归档。

2、archive_mode = on 上述参数为on,表示打开归档备份,可选的参数为on,off,always 默认值为off,所以要手动打开。

3、archive_command = 'test ! -f /mnt/server/archivedir/%f && cp %p /mnt/server/archivedir/%f' 该参数的默认值是一个空字符串,他的值可以是一条shell命令或者一个复杂的shell脚本。在shell脚本或命令中可以用 “%p” 表示将要归档的wal文件包含完整路径的信息的文件名,用“%f” 代表不包含路径信息的wal文件的文件名。

注意:wal_level和archive_mode参数修改都需要重新启动数据库才可以生效。而修改archive_command则不需要。所以一般配置新系统时,无论当时是否需要归档,这要建议将这两个参数开启。

八、如何计算WAL文件名

我们知道由三部分组成,那么又是如何计算呢?公式如下:

WAL segment file name = timelineId +(uint32)LSN−1 / (16M ∗ 256) + (uint32)(LSN − 1 / 16M) % 256

示例:

1、查看当前LSN位置

查看当前wal: select pg_walfile_name(pg_current_wal_lsn());

 

 2、这里的LSN是’ 1/C469AA30’ 我们转换为十进制数:

 

 3、利用公式计算:

 

 算出来的值与通过函数查询的一致:

 

九、计算WAL日志的大小

 

 10、查看wal生成频率和大小

–wal 文件生成数量

–linux ls --full-time stat filename

–pg_stat_file返回一个记录,其中包含

– 1 size 文件尺寸

– 2 access 最后访问时间戳(linux:最近访问) 、

– 3 modification 最后修改时间戳(linux:最近更改–) 、

– 4 change 最后文件状态改变时间戳(只支持 Unix 平台)(linux:最近改动) 、

– 5 creation 文件创建时间戳(只支持 Windows)

– 6 isdir 一个boolean指示它是否为目录 isdir

with tmp_file as ( select t1.file, t1.file_ls, (pg_stat_file(t1.file)).size as size, (pg_stat_file(t1.file)).access as access, (pg_stat_file(t1.file)).modification as last_update_time, (pg_stat_file(t1.file)).change as change, (pg_stat_file(t1.file)).creation as creation, (pg_stat_file(t1.file)).isdir as isdir from (select dir||'/'||pg_ls_dir(t0.dir) as file, pg_ls_dir(t0.dir) as file_ls from ( select '/pg13/pgdata/pg_wal'::text as dir ) t0 ) t1 where 1=1 order by (pg_stat_file(file)).modification desc ) select to_char(date_trunc('day',tf0.last_update_time),'yyyymmdd') as day_id, sum(case when date_part('hour',tf0.last_update_time) >=0 and date_part('hour',tf0.last_update_time) =0 and date_part('hour',tf0.last_update_time) =1 and date_part('hour',tf0.last_update_time) =2 and date_part('hour',tf0.last_update_time) =3 and date_part('hour',tf0.last_update_time) =4 and date_part('hour',tf0.last_update_time) =5 and date_part('hour',tf0.last_update_time) =6 and date_part('hour',tf0.last_update_time) =7 and date_part('hour',tf0.last_update_time) =8 and date_part('hour',tf0.last_update_time) =9 and date_part('hour',tf0.last_update_time) =10 and date_part('hour',tf0.last_update_time) =11 and date_part('hour',tf0.last_update_time) =12 and date_part('hour',tf0.last_update_time) =13 and date_part('hour',tf0.last_update_time) =14 and date_part('hour',tf0.last_update_time) =15 and date_part('hour',tf0.last_update_time) =16 and date_part('hour',tf0.last_update_time) =17 and date_part('hour',tf0.last_update_time) =18 and date_part('hour',tf0.last_update_time) =19 and date_part('hour',tf0.last_update_time) =20 and date_part('hour',tf0.last_update_time) =21 and date_part('hour',tf0.last_update_time) =22 and date_part('hour',tf0.last_update_time) =23 and date_part('hour',tf0.last_update_time)



【本文地址】

公司简介

联系我们

今日新闻

    推荐新闻

    专题文章
      CopyRight 2018-2019 实验室设备网 版权所有