首页 > 数据库 >PostgreSQL的WAL日志详解

PostgreSQL的WAL日志详解

时间:2024-08-11 15:28:27浏览次数:12  
标签:wal PostgreSQL bill checkpoint WAL pg 日志

PostgreSQL的WAL日志详解

1.WAL日志介绍

1.1 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已满。

其中1和2两点都和数据库的配置无关,我们暂时先不看,这里先介绍下checkpoint_timeout和max_wal_size两个参数。

checkpoint_timeout:
自动 WAL 检查点之间的最长时间,以秒计。合理的范围在 30 秒到 1 天之间。默认是 5 分钟(5min)。增加这个参数的值会增加崩溃恢复所需的时间。

bill@bill=>show checkpoint_timeout ;
 checkpoint_timeout 
--------------------
 30min
(1 row)

max_wal_size:
在自动 WAL检查点之间允许WAL 增长到的最大尺寸。这是一个软限制,在特殊的情况 下 WAL 尺寸可能会超过max_wal_size, 例如在重度负荷下、archive_command失败或者高的 wal_keep_segments设置。默认为 1 GB。增加这个参数可能导致崩溃恢复所需的时间。

bill@bill=>show max_wal_size ;
 max_wal_size 
--------------
 2GB
(1 row)

和max_wal_size相对应的还有个min_wal_size,这里简单介绍下:
只要 WAL 磁盘用量保持在这个设置之下,在检查点时旧的 WAL文件总是被回收以便未来使用,而不是直接被删除。

可能对oracle熟悉的人会觉得wal日志和redo还是有些不同,没错,oracle中redo是固定几个redo日志文件,然后轮着切换去写入,因此我们常常会在io高的数据库中看到redo切换相关的等待事件。
而在pg中wal日志是动态切换,从pg9.6开始采用这种模式。和oracle不同的是,pg中这种动态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以便内核将数据刷新到磁盘的时间足够(但不是太多)。

1.2 WAL日志解读

对数据库操作会以record为单位首先记录到wal日志中,在checkpoint时才对数据进行刷
盘(background writer会定时刷脏数据,但最终还是都由checkpoint确认都刷盘成功)。

聊了这么久wal日志,我们都还不知道wal日志在哪?长啥样。。。
wal日志位置:
$PGDATA/pg_wal(pg10之前叫pg_xlog)

wal日志文件命名规则:
我们看到的wal日志是这样的:000000010000000100000092
其中前8位:00000001表示timeline;
中间8位:00000001表示logid;
最后8位:00000092表示logseg

wal日志LSN编号规则:
1/920001F8(高32位/低32位)

对照关系:
1、wal日志的logseg前6位始终是0,后两位是LSN低32位/16MB(2*24),即LSN的前两位。如上例中logseg最后两位是92,LSN低32前两位也是92。
2、LSN在wal日志中的偏移量即LSN低32位中后24位对应的十进制值。
例如当前wal日志偏移量为504

bill=# select pg_walfile_NAME_OFFSET(pg_current_wal_lsn());
     pg_walfile_name_offset     
--------------------------------
 (000000010000000100000092,504)
(1 row)

bill=# select x'1F8'::int;
 int4 
------
  504
(1 row)

1.3 wal日志内部详解

接下来我们来看看wal日志里面究竟记录的是些什么内容。如果你直接查看wal日志,可能会收到下面这样的提示:

因为wal日志是二进制格式的文件,不过我们可以使用pg_waldump这个工具来将其转换成可读的文件。

例1:
首先来看看insert数据时wal日志里面记录了些什么。

bill=# begin;
BEGIN
bill=# select pg_current_wal_lsn();
 pg_current_wal_lsn 
--------------------
 1/92021290
(1 row)

bill=# insert into tbl values(1,'bill');
INSERT 0 1
bill=# select pg_current_wal_lsn();
 pg_current_wal_lsn 
--------------------
 1/92021308
(1 row)

bill=# end;
COMMIT

接下来我们看看wal日志里面内容:可以看到wal日志里面记录了上面的insert操作。

例2:
我们再看看update时wal日志里面记录的内容:

bill=# select pg_current_wal_lsn();
 pg_current_wal_lsn 
--------------------
 1/92021450
(1 row)

bill=# update tbl set info = 'foucus' where id = 1;
UPDATE 1
在这里插入图片描述

这里简单介绍下这条记录的内容:

rmgr: Heap        len (rec/tot):     65/   177, tx:        717, lsn: 1/92021450, prev 1/92021418, desc: HOT_UPDATE off 1 xmax 717 flags 0x20 ; new off 2 xmax 0, blkref #0: rel 1663/16395/17623 blk 0 FPW
  • rmgr: Heap :PostgreSQL内部将WAL日志归类到20多种不同的资源管理器。这条WAL记录所属资源管理器为 Heap,即堆表。除了Heap还有Btree,Transaction等。
  • len (rec/tot): 65/ 177:wal记录的长度。
  • tx: 717: 事务号。
  • lsn: 1/92021450:本条wal记录的lsn。
  • prev 1/92021418:上条wal记录的lsn。
  • desc: HOT_UPDATE off 1 xmax 717 flags 0x20 ; new off 2 xmax 0: 这是一条热更新类型的记录,旧数据
  • offset为1,xmax为717。旧tuple在page中的位置为1(即ctid的后半部分),新tuple在page中的位置为2。
  • blkref #0: rel 1663/16395/17623 blk 0 :引用的第一个page(新tuple所在page)所属的堆表文件为1663/13543/16469,块号为0(即ctid的前半部分)。

2 流复制

3.1 日志提交过程

从上图我们可以看到流复制中日志提交的大致流程为:
1、事务commit后,日志在主库写入wal日志,还需要根据配置的日志同步级别,等待从库反馈的接收结果。
2、主库通过日志传输进程将日志块传给从库,从库接收进程收到日志开始回放,最终保证主从数据一致性。

2.2 流复制同步级别

PostgreSQL通过配置synchronous_commit (enum)参数来指定事务的同步级别。我们可以根据实际的业务需求,对不同的事务,设置不同的同步级别。

synchronous_commit = off                # synchronization level;  
                                        # off, local, remote_write, or on  
  • remote_apply:事务commit或rollback时,等待其redo在primary、以及同步standby(s)已持久化,并且其redo在同步

  • standby(s)已apply。

  • on:事务commit或rollback时,等待其redo在primary、以及同步standby(s)已持久化。

  • remote_write:事务commit或rollback时,等待其redo在primary已持久化; 其redo在同步standby(s)已调用write接口(写到 OS, 但是还没有调用持久化接口如fsync)。

  • local:事务commit或rollback时,等待其redo在primary已持久化;

  • off:事务commit或rollback时,等待其redo在primary已写入wal buffer,不需要等待其持久化;

不同的事务同步级别对应的数据安全级别越高,对应的对性能影响也就越大。上述从上至下安全级别越来越低。

详细的同步流复制原理见:

CommitTransaction @ src/backend/access/transam/xact.c   
RecordTransactionCommit @ src/backend/access/transam/xact.c  

标签:wal,PostgreSQL,bill,checkpoint,WAL,pg,日志
From: https://www.cnblogs.com/zreo2home/p/18353401

相关文章

  • PostgreSQL一主一从高可用搭建
    1.PostgreSQL一主一从高可用搭建(VIP)IP主机名角色192.168.198.146test11主服务器192.168.198.143test12备用服务器192.168.198.144test13见证服务器一、基本环境配置1、hosts文件配置(所有节点)vim/etc/hosts#新增192.168.198.146msp-app01192......
  • 轻松找回:如何在PostgreSQL 16中重置忘记的数据库密码
    目录1.引言2.PostgreSQL16的新特性简介3.解决方法概述4.方法一:通过修改`pg_hba.conf`文件重置密码5.方法二:通过命令行进入单用户模式6.方法三:使用pgAdmin工具重置密码7.总结与最佳实践写在以后1.引言你有没有过这样的经历?当你满怀期待地打开电脑准备工作时,......
  • 240730-PostgreSQL的逻辑备份与物理备份
    PostgreSQL的逻辑备份与物理备份简介制定备份和恢复计划是每一个DBA最重要的工作之一,它决定了数据的有效性和完整性。也可以搭建跨越不同数据中心的流复制集群,能有效的帮助你避免单点故障。但是只有一份有效的备份能够帮助从delete或者drop的误操中恢复数据。制定备份和恢复计......
  • PostgreSQL的查询详解
    PostgreSQL的查询详解1.表表达式表表达式计算一个表。该表表达式包含一个FROM子句,该子句后面可以根据需要选用WHERE、GROUPBY和HAVING子句。最简单的表表达式只是引用磁盘上的一个表,一个所谓的基本表,但是我们可以用更复杂的表表达式以多种方法修改或组合基本表。表表达......
  • PostgreSQL的体系结构
    1.体系架构1、应用程序访问接口整个应用架构中,Postgresql数据库位于操作系统和应用程序之间,不同的编程语言使用不同的驱动程序链接到Postgresql数据库上,驱动分为两类:1.使用纯语言实现的Postgresql驱动,如JDBC、.NET等方式,这种链接方式不需要libpq库。2.通过包装Postgresql的......
  • PostgreSQL的数据类型
    PostgreSQL的数据类型1.布尔类型1.1布尔值对应表在Postgresql数据库中Boolean的值除了“true”(真)、“false”(假),还有一个“unknown”(未知)状态。如果是unknown时用NULL表示。布尔类型在Postgresql中可以用不带引号的TRUE或FALSE表示,也可以用更多表示真和假的带引号的字符表示:......
  • PostgreSQL的物理备份
    PostgreSQL的物理备份1.简单了解1.1pg_basebackup备份1.1.1简介pg_basebackup是从postgresql9.1版本开始提供的一个方便基础备份的工具。pg_basebackup用于对正在运行的PostgreSQL数据库集群进行基本备份。备份是在不影响数据库的其他客户端的情况下进行的,并且可以用于时......
  • PostgreSQL-连续归档和时间点恢复
    PostgreSQL-连续归档和时间点恢复(PITR)PostgreSQL始终在群集数据目录的pg_wal/子目录中维护一个预写日志(WAL)。该日志记录对数据库数据文件所做的每一项更改。此日志主要用于崩溃安全性:如果系统崩溃,可以通过“重放”自上次检查点以来所做的日志条目来将数据库恢复到一致性......
  • PostgreSQL的同步异步复制简介及互相转换
    PostgreSQL的同步/异步复制简介及互相转换一、介绍1.概念1.1.同步流复制同步流复制就是当主库发生变化,比如有一条DML语句产生了WAL日志后,通过后台进程传送到备库,备库必须要应用这个日志,然后向主库返回一个成功应用的信号,主库才可以成功的commit;否则主库会一直等待到备库成功......
  • PostgreSQL的一主一从集群搭建部署
    1.PostgreSQL的一主一从集群搭建部署1.目标​ 掌握Postgresql数据库主从部署搭建配置2.脉络部署规划PostgreSQL单节点安装PostgreSQL主从部署配置主从同步验证3.部署搭建3.1基础准备1.1创建两台虚拟机虚拟机名IPhostname主从划分test11192.168.198......