暂无图片
暂无图片
2
暂无图片
暂无图片
暂无图片

PostgreSQL | WAL文件,你需要知道的知识点



前言

今天是个晴朗的日子,太阳升起来了,经历了倒春寒,熟悉的春天又回来了。
WAL (Write Ahead Log)是学习PostgreSQL的一个非常重要的文件,今天我们就来谈谈 WAL文件的一些基础知识点。

WAL

WAL也叫预写日志文件,它是记录数据库所有更新操作的日志,其主要作用是备份,PRIP (基于时间点恢复)以及流复制。默认情况下,WAL文件存储在$ PGDATA/pg_wal文件夹下,文件名是带有序列号的,大小为16 MB。

[postgres@freebsd-test /app/pgdata/pg_wal]$ ls -lrt
total 2441
drwx------  2 postgres  postgres         2 Mar  2 04:07 archive_status
-rw-------  1 postgres  postgres  16777216 Mar  3 00:01 000000010000000000000001

您可以在创建数据库时指定--wal-segsize来修改wal文件大小。

[postgres@freebsd-test ~]$ initdb -D $PGDATA -E UTF-8 --wal-segsize 64  

[postgres@freebsd-test /app/pgdata/pg_wal]$ ls -lsh
total 2201
2201 -rw-------  1 postgres  postgres    64M Mar  3 00:39 000000010000000000000001
   1 drwx------  2 postgres  postgres     2B Mar  3 00:39 archive_status
   
[postgres@freebsd-test /app/pgdata/pg_wal]$ psql
psql (13.2)
Type "help" for help.

postgres=# SHOW wal_segment_size;
 wal_segment_size 
------------------
 64MB
(1 row)   

观察到数据库的参数wal_segment_size
已被修改为64 MB。
WAL文件是二进制文件,如果想研究它,可以使用自带的pg_waldump
对其进行查看。

pg_waldump /app/pgdata/pg_wal/000000010000000000000001 

你会发现其中有个重要的内容叫做 LSN (日志序列号)。在官方文档中的解释为:在内部,一个LSN是一个64位整数,表示预写式日志流中的一个字节位置。它被打印成两个最高 8 位的十六进制数,中间用斜线分隔,例如16/B374D848。当执行 PIRP (基于时间点回复)时,我们可以指定一个 LSN号来进行恢复。

WAL切换

WAL默认大小是16 MB,如果超过16 MB,就会写到下一个 WAL中。举例来说,当我继续写入000000010000000000000001时,此文件超过了16MB。下一步就会写入000000010000000000000002。通过将pg_current_wal_lsn()
函数与 select pg_walfile_name()
函数相结合,就可以找到当前正在写入的WAL。
pg_current_wal_lsn()
函数返回当前LSN的值。

postgres=# select pg_current_wal_lsn();
 pg_current_wal_lsn 
--------------------
 0/1BC1848
(1 row)

pg_walfile_name()
函数是将LSN作为参数,然后返回LSN所属WAL的文件名的函数。

postgres=# SELECT pg_walfile_name('0/1BC1848');
     pg_walfile_name      
--------------------------
 000000010000000000000001
(1 row)

postgres=# SELECT pg_walfile_name(pg_current_wal_lsn());
     pg_walfile_name      
--------------------------
 000000010000000000000001
(1 row)

WAL切换可以手工完成,也可以在超过16MB时自动完成。可使用select pg_switch_wal()
函数对WAL文件进行切换。

postgres=# SELECT pg_walfile_name(pg_current_wal_lsn());
     pg_walfile_name      
--------------------------
 000000010000000000000001
(1 row)

postgres=# select pg_switch_wal();
 pg_switch_wal 
---------------
 0/1BC1860
(1 row)

postgres=# SELECT pg_walfile_name(pg_current_wal_lsn());
     pg_walfile_name      
--------------------------
 000000010000000000000001
(1 row)

postgres=# SELECT pg_walfile_name(pg_current_wal_lsn());
     pg_walfile_name      
--------------------------
 000000010000000000000002
(1 row)

值得注意的是,在这里完成了pg_switch_wal()
函数的切换后,通过函数pg_walfile_name查不会立即改变,它需要等上几秒才会刷新。

WAL缓冲区

为了快速写操作,WAL首先写到内存,然后异步写到磁盘。写入内存的区域称为WAL缓冲区,由参数wal_buffer
控制,默认值为shared_buffers值的1/32。并且WAL Writter进程将以200ms的默认设置将内存中的WAL缓冲区写入磁盘。它由bgwriter_delay
参数控制。

postgres=# show wal_buffers;
 wal_buffers 
-------------
 4MB
(1 row)

postgres=# show bgwriter_delay ;
 bgwriter_delay 
----------------
 200ms
(1 row)

以下情况wal writer进程会把缓冲区数据写入磁盘,这样就能最大程度避免了崩溃时数据不一致的情况。

  • wal writer定期执行
  • 执行COMMIT 时
  • 执行checkpoint时
  • 运行vacuum时
  • WAL缓冲区溢出时
  • 共享缓冲区溢出时

WAL级别

WAL有一个名为wal_level的设置,用于指定日志输出的详细程度。默认值为replica
,但是您可以将其更改为logical
以进行逻辑复制,如果最小日志足够,则可以将其更改为minimal。

WAL有一个名为wal_level的设置,用来指定日志输出详细程度。缺省值是replica
,但可以将其更改为logical
,以便进行逻辑复制,如果最小日志足够,则可以将其更改为minimal。

在旧版本的PostgreSQL中,wal_level的默认设置就是minimal。

WAL设置总结如下:

「wal_level」行为
minimal记录足够的日志以从崩溃或突然关闭中恢复。用于减少日志并加快速度
replica记录足够执行流式复制需要的日志
logical与replica大致相同,但是添加了支持逻辑解码所需的信息。注意,这将导致日志数量增加

如果wal_level设置为Minimum,则以下操作不会记录在WAL中,这将加快处理过程。

  • ALTER … SET TABLESPACE
  • CLUSTER
  • CREATE TABLE
  • REFRESH MATERIALIZED VIEW (without CONCURRENTLY)
  • REINDEX
  • TRUNCATE

使用logical将增加WAL的大小,特别是将许多表设置为REPLICA IDENTITY FULL时,并执行许多UPDATE和DELETE语句。

归档

归档功能可以将WAL复制到另一个目录。若复制目标为共享区域(如 NSF或其他主机),则可以将其用于备份和 PITR前滚(基于时间点的恢复)。

归档所需的参数概述如下。

参数描述
archive_mode设置是否启用归档。这里要注意,如果wal_level设置为minimal,是无法启用它的。
archive_command使用本地shell指令来执行归档传输wal文件。例如通常使用的cp文件到nfs系统,rsync到远程主机的文件系统。
archive_timeout尝试归档的超时时间,推荐值约为60秒,如果要指定较短的时间间隔并执行快速的WAL传输,建议执行流式传输而不是归档。

接下来我们来配置一个rsync归档,服务器先安装 rsync软件包,然后切换到PostgreSQL用户。配置PostgreSQL用户能和远端服务器进行ssh免密钥连接。

root@freebsd-test:~ # pkg install rsync

[postgres@freebsd-test ~]$ ssh-keygen -t rsa
[postgres@freebsd-test ~]$ ssh-copy-id -i ~/.ssh/id_rsa.pub postgres@192.168.56.125
The authenticity of host '192.168.56.125 (192.168.56.125)' can't be established.
RSA key fingerprint is SHA256:efAuU0ijAy7MzSFdfn30Baedbz2NZoJTgKOdFFm7bx8.
No matching host key fingerprint found in DNS.
Are you sure you want to continue connecting (yes/no)? yes
Warning: Permanently added '192.168.56.125' (RSA) to the list of known hosts.
postgres@192.168.56.125's password: 
[postgres@freebsd-test ~]$ ssh postgres@192.168.56.125 date
Tue Mar  2 14:09:29 UTC 2021

在完成配置之后,您可以设置数据库参数。

postgres=# alter system set archive_mode=on;
ALTER SYSTEM
postgres=# alter system set archive_command='rsync -a %p postgres@192.168.56.125:/home/postgres/%f';
ALTER SYSTEM

重新启动数据库,查看归档状态。

[postgres@freebsd-test ~]$ service postgresql restart

--备份端机器
[postgres@centos8 ~]$ ls -lrt
total 49152
-rw-------. 1 postgres postgres 16777216 Mar  2  2021 000000010000000000000002
-rw-------. 1 postgres postgres 16777216 Mar  2  2021 000000010000000000000003
-rw-------. 1 postgres postgres 16777216 Mar  2  2021 000000010000000000000004

现在归档文件已被传送到远端。当在此时备端发生异常(网络中断,写不进去等情况)时,可以进入archive_status目录,这里会对传输失败的文件标注了. ready,而传输成功的文件则标注. done。

--备份端机器
[root@centos8 ~]# cd /home/
[root@centos8 home]# chown root:root postgres

--PostgreSQL服务器
root@freebsd-test:/app/pgdata/pg_wal # ls -lrt
total 63
-rw-------  1 postgres  postgres  16777216 Mar  3 06:15 000000010000000000000002
-rw-------  1 postgres  postgres  16777216 Mar  3 06:15 000000010000000000000003
-rw-------  1 postgres  postgres  16777216 Mar  3 06:16 000000010000000000000004
-rw-------  1 postgres  postgres  16777216 Mar  3 06:19 000000010000000000000005
drwx------  2 postgres  postgres         6 Mar  3 06:19 archive_status
-rw-------  1 postgres  postgres  16777216 Mar  3 06:19 000000010000000000000006
root@freebsd-test:/app/pgdata/pg_wal # cd archive_status
root@freebsd-test:/app/pgdata/pg_wal/archive_status # ls -lrt
total 2
-rw-------  1 postgres  postgres  0 Mar  3 06:15 000000010000000000000002.done
-rw-------  1 postgres  postgres  0 Mar  3 06:15 000000010000000000000003.done
-rw-------  1 postgres  postgres  0 Mar  3 06:16 000000010000000000000004.done
-rw-------  1 postgres  postgres  0 Mar  3 06:19 000000010000000000000005.ready

现在返回备端机器,将权限修改回正常状态。然后在PostgreSQL服务器上查看archive_status,就会看到05.done。代表05已经传过去了。

--备份端机器
[root@centos8 home]# chown postgres:postgres postgres

--PostgreSQL服务器
root@freebsd-test:/app/pgdata/pg_wal/archive_status # ls -lrt
total 1
-rw-------  1 postgres  postgres  0 Mar  3 06:19 000000010000000000000005.done

--备份端机器
[root@centos8 postgres]# ls -lrt
total 65536
-rw-------. 1 postgres postgres 16777216 Mar  2  2021 000000010000000000000002
-rw-------. 1 postgres postgres 16777216 Mar  2  2021 000000010000000000000003
-rw-------. 1 postgres postgres 16777216 Mar  2  2021 000000010000000000000004
-rw-------. 1 postgres postgres 16777216 Mar  2  2021 000000010000000000000005

尾声


上述就是今天wal文件中需要知道的一些知识点。都是比较基础的点,要牢牢把握啊。



励志成为PostgreSQL大神

长按关注吧





文章转载自励志成为PostgreSQL大神,如果涉嫌侵权,请发送邮件至:contact@modb.pro进行举报,并提供相关证据,一经查实,墨天轮将立刻删除相关内容。

评论