前言
今天是个晴朗的日子,太阳升起来了,经历了倒春寒,熟悉的春天又回来了。
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
尾声
励志成为PostgreSQL大神
长按关注吧