进阶数据库系列(二十一):PostgreSQL 数据目录同步工具 pg_rewind

进阶数据库系列(十五):PostgreSQL 主从同步原理与实践 PostgreSql 数据库主库意外宕机,手动切换主备数据库流程。环境:PostgreSql v12 + Centos 7主库:192.168.100.170备库:192.168.100.171。 阅读详情

前面介绍了 PostgreSQL 主从复制、高可用方案、基于 Patroni 高可用架构部署及故障切换、 基于 repmgr 高可用架构实践、基于 pgpool 实现读写分离实践、数据库备份与恢复等相关的知识点,今天我将详细的为大家介绍 PostgreSQL 主从数据目录同步工具 pg_rewind相关知识,希望大家能够从中收获多多!如有帮助,请点在看、转发支持一波!!!

pg_rewind 概述

pg_rewind 是 postgresql 主从数据库之同步数据目录的工具。

pg_rewind 相比 pg_basebackup 和 rsync 这样的工具来说,优势是它不需要从源目录拷贝所有的数据文件,而是会对比时间线发生偏离的点,只拷贝变化过的文件,这样对于数据量很大的情况下速度更快。

pg_rewind对服务端的要求

数据库开启 checksums 或者设置wal_log_hints 参数为on,一般采用后者。

wal_log_hints=on
pg_rewind对权限的要求

pg_rewind工具其实只依赖如下以下四个文件读取系统函数的权限:

pg_ls_dir()
pg_read_file()
pg_read_binary_file()
pg_stat_file()

这四个函数在PostgreSQL 11版本之前只能超级用户才有权限使用。从PostgreSQL 11开始,pg_rewind可以不依赖超级用户只需要分配这几个系统函数权限。

pg_rewind对流复制的功能改进
-R / --write-recovery-conf

使用这个选项可以让pg_rewind帮我们自动创建流复制相关的恢复配置文件,并将指定选项–source-server里的连接字符串附加到postgresql.auto.conf中的primary_conninfo参数里,这个选项可以用来将原主库快速恢复为备库。

-c / --restore-target-wal

在进行pg_rewind恢复时,源库pg_wal目录下的wal文件可能因为某些原因不存在,因此会出现下面的报错提示:

pg_rewind: error: could not open file “/var/lib/pgsql/data/pg_wal/000000010000000000000002”: No such file or directory

当出现这种情况时PostgreSQL可以使用restore_command参数配置的命令来获取所需的WAL文件。更多关于 PostgreSQL 系列的学习文章,请参阅:PostgreSQL 数据库,本系列持续更新中。

pg_rewind 原理

  • 1.确定新Master和旧Master数据一致性的Checkpoint位置.在该位置上,新Master和旧Master数据完全一致.这可以通过读取新旧Master节点时间线历史文件可以获得,该文件位于$PGDATA/pg_wal/目录下,文件名称为XX.history

  • 2.旧Master节点根据上一步获取的Checkpoint读取本机日志文件WAL Record,获取在此Checkpoint之后出现变化的Block,并以链表的方式存储Block编号等信息

  • 3.根据第2步获取的Block信息从新Master节点拷贝相应的Block,替换旧Master节点相应的Block

  • 4.拷贝新Master节点上除数据文件外的所有其他文件,包括配置文件等(如果拷贝数据文件,与备份方式搭建区别不大)

  • 5.旧Master启动数据库,应用从Checkpoint开始后的WAL Record.

  • 更多关于 PostgreSQL 系列的学习文章,请参阅:PostgreSQL 数据库,本系列持续更新中。

pg_rewind 语法

pg_rewind [option...] { -D | --target-pgdata } directory { --source-pgdata=directory | --source-server=connstr } 
参数说明
-D directory 或 --target-pgdata=directory:#此选项指定与源同步的目标数据目录。在运行pg_rewind之前,必须干净关闭目标服务器。

–source-pgdata=directory:#指定要与之同步的源服务器的数据目录的文件系统路径。此选项要求干净关闭源服务器。

–source-server=connstr:#指定要连接到源 PostgreSQL 服务器的 libpq 连接字符串。连接必须是具有超级用户访问权限的正常(非复制)连接。此选项要求源服务器正在运行,而不是处于恢复模式。

-R 或 --write-recovery-conf:#创建standby.signal并将连接设置附加到输出目录中的 postgresql.auto.conf 中。–source-server对于此选项是必需的。

-n 或 --dry-run:#除了实际修改目标目录之外,执行所有操作。

-N 或 --no-sync:#默认情况下,pg_rewind 将等待所有文件安全地写入磁盘。 此选项会导致 pg_rewind 不等待即可返回,这更快,但意味着后续操作系统崩溃会使同步数据目录损坏。通常情况,此选项可用于测试,但不应使用于生产安装。

-P 或 --progress:#启用进度报告。在从源集簇拷贝数据时,打开这个选项将会发送一个近似的进度报告。

-c 或 --restore-target-wal:#如果在 pg_wal 目录中不再可用这些文件,请使用在目标群集配置中定义的 restore_command 从WAL存档中检索WAL文件。

–debug:#打印冗长的调试输出,这主要对于调试pg_rewind的开发者有用。

–no-ensure-shutdown:#pg_rewind 要求目标服务器在重放之前彻底关闭。默认情况下,如果目标服务器没有完全关闭,pg_rewind 会以单用户模式启动目标服务器,先完成崩溃恢复,然后将其停止。通过传递这个选项,如果服务器没有完全关闭,pg_rewind 会跳过这个并立即出错。 在这种情况下,用户应该自己处理这种情况。

-V --version:#显示版本信息然后退出。

pg_rewind 测试

测试环境
  • 主库:192.168.13.31

  • 备库:192.168.13.32

  • 测试数据库版本:PostgreSQL 14.5

两节点配置好流复制

测试过程

配置测试环境,主备一致:

 /*192.168.13.31*/ 
[postgres@duqk01 ~]$ psql
psql (14.5)
Type "help" for help.

postgres=# show wal_log_hints;
 wal_log_hints 
---------------
 on
(1 row)

postgres=# show full_page_writes;
 full_page_writes 
------------------
 on
(1 row)

postgres=# show max_standby_streaming_delay;
 max_standby_streaming_delay 
-----------------------------
 -1
(1 row)

postgres=# show restore_command;
   restore_command    
----------------------
 cp /data/pgarc/%f %p
(1 row)

postgres=# show archive_mode;
 archive_mode 
--------------
 always
(1 row)

postgres=# show archive_command;
   archive_command    
----------------------
 cp %p /data/pgarc/%f
(1 row)

postgres=# 

postgres=# select * from pg_replication_slots\gx
-[ RECORD 1 ]-------+----------
slot_name           | rep
plugin              | 
slot_type           | physical
datoid              | 
database            | 
temporary           | f
active              | t
active_pid          | 9888
xmin                | 742
catalog_xmin        | 
restart_lsn         | 0/6000110
confirmed_flush_lsn | 
wal_status          | reserved
safe_wal_size       | 
two_phase           | f

postgres=# 

创建测试数据,并在备库上开启长事物:

 /*192.168.13.31*/ 
postgres=# create table t(id int);
CREATE TABLE
postgres=# insert into t values(1);
INSERT 0 1
postgres=# create table tt(like t);
CREATE TABLE
postgres=# insert into tt values(1); 
INSERT 0 1
postgres=# 

* /192.168.13.32/ *

[postgres@duqk02 ~]$ psql
psql (14.5)
Type "help" for help.

postgres=# begin;
BEGIN
postgres=*# select * from tt;
 id 
----
  1
(1 row)

postgres=*# select * from t; 
 id 
----
  1
(1 row)

postgres=*# 

备库开启长事物,主库对数据库修改

* /192.168.13.31/ *
终端1
postgres=# drop table tt;
DROP TABLE
postgres=# insert into t select generate_series(1,10000);
INSERT 0 10000
postgres=# checkpoint;select pg_switch_wal();
CHECKPOINT
 pg_switch_wal 
---------------
 0/60C1480
(1 row)

postgres=# checkpoint;select pg_switch_wal();
CHECKPOINT
 pg_switch_wal 
---------------
 0/70000F0
(1 row)

postgres=# insert into t select generate_series(1,10000);
INSERT 0 10000
postgres=# checkpoint;select pg_switch_wal();            
CHECKPOINT
 pg_switch_wal 
---------------
 0/809D4D8
(1 row)

postgres=# checkpoint;select pg_switch_wal();
CHECKPOINT
 pg_switch_wal 
---------------
 0/90000F0
(1 row)

postgres=# insert into t select generate_series(1,10000);
INSERT 0 10000
postgres=# insert into t select generate_series(1,10000);
INSERT 0 10000
postgres=# checkpoint;select pg_switch_wal();            
CHECKPOINT
 pg_switch_wal 
---------------
 0/A13A848
(1 row)

postgres=# checkpoint;select pg_switch_wal();
CHECKPOINT
 pg_switch_wal 
---------------
 0/B16E5C0
(1 row)

postgres=# insert into t select generate_series(1,10000);
INSERT 0 10000
postgres=# checkpoint;select pg_switch_wal();            
CHECKPOINT
 pg_switch_wal 
---------------
 0/C0A4D48
(1 row)

postgres=# checkpoint;select pg_switch_wal();
CHECKPOINT
 pg_switch_wal 
---------------
 0/D0000F0
(1 row)

postgres=# checkpoint;select pg_switch_wal();
CHECKPOINT
 pg_switch_wal 
---------------
 0/E0000F0
(1 row)

postgres=# 

终端2
[postgres@duqk01 pg_wal]$ ls -trl
total 65540
-rw------- 1 postgres postgres      338 Sep  7 16:34 000000010000000000000004.00000028.backup
-rw------- 1 postgres postgres 16777216 Jan 13 08:56 00000001000000000000000C
-rw------- 1 postgres postgres 16777216 Jan 13 08:56 00000001000000000000000D
-rw------- 1 postgres postgres 16777216 Jan 13 08:56 00000001000000000000000E
drwx------ 2 postgres postgres      170 Jan 13 08:56 archive_status
-rw------- 1 postgres postgres 16777216 Jan 13 08:57 00000001000000000000000F
[postgres@duqk01 pg_wal]$ 
---当前主库的最新的wal日志为:00000001000000000000000F

[postgres@duqk01 pg_wal]$ ls -trl /data/pgarc/
total 229380
-rw------- 1 postgres postgres 16777216 Sep  7 16:13 000000010000000000000001
-rw------- 1 postgres postgres 16777216 Sep  7 16:29 000000010000000000000002
-rw------- 1 postgres postgres 16777216 Sep  7 16:34 000000010000000000000003
-rw------- 1 postgres postgres 16777216 Sep  7 16:34 000000010000000000000004
-rw------- 1 postgres postgres      338 Sep  7 16:34 000000010000000000000004.00000028.backup
-rw------- 1 postgres postgres 16777216 Sep  7 16:44 000000010000000000000005
-rw------- 1 postgres postgres 16777216 Jan 13 08:56 000000010000000000000006
-rw------- 1 postgres postgres 16777216 Jan 13 08:56 000000010000000000000007
-rw------- 1 postgres postgres 16777216 Jan 13 08:56 000000010000000000000008
-rw------- 1 postgres postgres 16777216 Jan 13 08:56 000000010000000000000009
-rw------- 1 postgres postgres 16777216 Jan 13 08:56 00000001000000000000000A
-rw------- 1 postgres postgres 16777216 Jan 13 08:56 00000001000000000000000B
-rw------- 1 postgres postgres 16777216 Jan 13 08:56 00000001000000000000000C
-rw------- 1 postgres postgres 16777216 Jan 13 08:56 00000001000000000000000D
-rw------- 1 postgres postgres 16777216 Jan 13 08:56 00000001000000000000000E
[postgres@duqk01 pg_wal]$ 

备库确认复制延迟,但是此时wal日志和归档日志都已经传到备库上了的

* /192.168.13.32/ *
终端1
postgres=*#  select * from tt;
 id 
----
  1
(1 row)

postgres=*#  select * from t; 
 id 
----
  1
(1 row)

postgres=*# 

终端2
[postgres@duqk02 pg_wal]$ ls -trl
total 196612
-rw------- 1 postgres postgres 16777216 Sep  7 16:34 000000010000000000000004
-rw------- 1 postgres postgres 16777216 Jan 13 08:54 000000010000000000000005
-rw------- 1 postgres postgres 16777216 Jan 13 08:56 000000010000000000000006
-rw------- 1 postgres postgres 16777216 Jan 13 08:56 000000010000000000000007
-rw------- 1 postgres postgres 16777216 Jan 13 08:56 000000010000000000000008
-rw------- 1 postgres postgres 16777216 Jan 13 08:56 000000010000000000000009
-rw------- 1 postgres postgres 16777216 Jan 13 08:56 00000001000000000000000A
-rw------- 1 postgres postgres 16777216 Jan 13 08:56 00000001000000000000000B
-rw------- 1 postgres postgres 16777216 Jan 13 08:56 00000001000000000000000C
-rw------- 1 postgres postgres 16777216 Jan 13 08:56 00000001000000000000000D
-rw------- 1 postgres postgres 16777216 Jan 13 08:56 00000001000000000000000E
drwx------ 2 postgres postgres     4096 Jan 13 08:56 archive_status
-rw------- 1 postgres postgres 16777216 Jan 13 08:57 00000001000000000000000F
[postgres@duqk02 pg_wal]$

---备库的最新的wal日志也为:00000001000000000000000F
[postgres@duqk02 pg_wal]$ ls -trl /data/pgarc/
total 163840
-rw------- 1 postgres postgres 16777216 Jan 13 08:54 000000010000000000000005
-rw------- 1 postgres postgres 16777216 Jan 13 08:56 000000010000000000000006
-rw------- 1 postgres postgres 16777216 Jan 13 08:56 000000010000000000000007
-rw------- 1 postgres postgres 16777216 Jan 13 08:56 000000010000000000000008
-rw------- 1 postgres postgres 16777216 Jan 13 08:56 000000010000000000000009
-rw------- 1 postgres postgres 16777216 Jan 13 08:56 00000001000000000000000A
-rw------- 1 postgres postgres 16777216 Jan 13 08:56 00000001000000000000000B
-rw------- 1 postgres postgres 16777216 Jan 13 08:56 00000001000000000000000C
-rw------- 1 postgres postgres 16777216 Jan 13 08:56 00000001000000000000000D
-rw------- 1 postgres postgres 16777216 Jan 13 08:56 00000001000000000000000E
[postgres@duqk02 pg_wal]$ 

在主库上通过SQL查询,再次确认复制延迟

 /*192.168.13.31*/ 

postgres=# select pg_wal_lsn_diff(pg_current_wal_lsn(),sent_lsn) sent_wal,pg_wal_lsn_diff(pg_current_wal_lsn(),write_lsn) write_wal,pg_wal_lsn_diff(pg_current_wal_lsn(),flush_lsn) flush_wal,pg_wal_lsn_diff(pg_current_wal_lsn(),replay_lsn) replay_wal from pg_stat_replication;
 sent_wal | write_wal | flush_wal | replay_wal 
----------+-----------+-----------+------------
        0 |         0 |         0 |  151253816
(1 row)

postgres=#  

在备库有复制延迟的前提下,提升备库为主库:

* /192.168.13.32/ *
终端2
[postgres@duqk02 ~]$ pg_ctl promote -D /data/pgdata
waiting for server to promote............................................................... stopped waiting
pg_ctl: server did not promote in time
[postgres@duqk02 ~]$ 

---原因是因为备库上有长事物在运行,所以promote会失败。

[postgres@duqk02 ~]$ pg_ctl promote -D /data/pgdata
waiting for server to promote..... done
server promoted
[postgres@duqk02 ~]$ 
---在运行的过程中结束终端1的长事物

原备库提升为主库之后,创建流复制所需的复制槽,并模拟数据变动

 /*192.168.13.32*/ 
终端1
postgres=# select count(*) from t; 
 count 
-------
 50001
(1 row)

postgres=# select count(*) from tt; 
ERROR:  relation "tt" does not exist
LINE 1: select count(*) from tt;
                             ^
postgres=# select * from pg_replication_slots;
 slot_name | plugin | slot_type | datoid | database | temporary | active | active_pid | xmin | catalog_xmin | restart_lsn | confirmed_flush_lsn | wal_status | safe_wal_size | two_phase 
-----------+--------+-----------+--------+----------+-----------+--------+------------+------+--------------+-------------+---------------------+------------+---------------+-----------
(0 rows)

postgres=# select * from pg_create_physical_replication_slot('rep');
 slot_name | lsn 
-----------+-----
 rep       | 
(1 row)

postgres=# select * from pg_replication_slots;                      
 slot_name | plugin | slot_type | datoid | database | temporary | active | active_pid | xmin | catalog_xmin | restart_lsn | confirmed_flush_lsn | wal_status | safe_wal_size | two_phase 
-----------+--------+-----------+--------+----------+-----------+--------+------------+------+--------------+-------------+---------------------+------------+---------------+-----------
 rep       |        | physical  |        |          | f         | f      |            |      |              |             |                     |            |               | f
(1 row)

postgres=#
postgres=# truncate table t;
TRUNCATE TABLE
postgres=# 
postgres=# insert into t select generate_series(1,100);
INSERT 0 100
postgres=# checkpoint;select pg_switch_wal();
CHECKPOINT
 pg_switch_wal 
---------------
 0/F225258
(1 row)

postgres=# checkpoint;select pg_switch_wal();
CHECKPOINT
 pg_switch_wal 
---------------
 0/100000F0
(1 row)

postgres=# 
postgres=# insert into t select generate_series(1,100);
INSERT 0 100
postgres=# checkpoint;select pg_switch_wal();          
CHECKPOINT
 pg_switch_wal 
---------------
 0/110028B0
(1 row)

postgres=# checkpoint;select pg_switch_wal();
CHECKPOINT
 pg_switch_wal 
---------------
 0/120000F0
(1 row)

postgres=# checkpoint;select pg_switch_wal();
CHECKPOINT
 pg_switch_wal 
---------------
 0/130000F0
(1 row)

postgres=# insert into t select generate_series(1,100);
INSERT 0 100
postgres=# checkpoint;select pg_switch_wal();          
CHECKPOINT
 pg_switch_wal 
---------------
 0/1400E128
(1 row)

postgres=# 

终端2
[postgres@duqk02 pg_wal]$ ls -trl
total 196612
-rw------- 1 postgres postgres 16777216 Jan 13 08:56 000000020000000000000016
-rw------- 1 postgres postgres 16777216 Jan 13 08:56 000000020000000000000017
-rw------- 1 postgres postgres 16777216 Jan 13 08:56 000000020000000000000018
-rw------- 1 postgres postgres 16777216 Jan 13 08:56 000000020000000000000019
-rw------- 1 postgres postgres 16777216 Jan 13 08:57 00000002000000000000001B
-rw------- 1 postgres postgres       41 Jan 13 08:59 00000002.history
-rw------- 1 postgres postgres 16777216 Jan 13 09:01 00000002000000000000001A
-rw------- 1 postgres postgres 16777216 Jan 13 09:01 00000002000000000000001C
-rw------- 1 postgres postgres 16777216 Jan 13 09:01 00000002000000000000001D
-rw------- 1 postgres postgres 16777216 Jan 13 09:01 000000020000000000000012
-rw------- 1 postgres postgres 16777216 Jan 13 09:01 000000020000000000000013
-rw------- 1 postgres postgres 16777216 Jan 13 09:02 000000020000000000000014
drwx------ 2 postgres postgres      146 Jan 13 09:02 archive_status
-rw------- 1 postgres postgres 16777216 Jan 13 09:02 000000020000000000000015
[postgres@duqk02 pg_wal]$ ls -trl /data/pgarc/
total 262148
-rw------- 1 postgres postgres 16777216 Jan 13 08:56 000000010000000000000006
-rw------- 1 postgres postgres 16777216 Jan 13 08:56 000000010000000000000007
-rw------- 1 postgres postgres 16777216 Jan 13 08:56 000000010000000000000008
-rw------- 1 postgres postgres 16777216 Jan 13 08:56 000000010000000000000009
-rw------- 1 postgres postgres 16777216 Jan 13 08:56 00000001000000000000000A
-rw------- 1 postgres postgres 16777216 Jan 13 08:56 00000001000000000000000B
-rw------- 1 postgres postgres 16777216 Jan 13 08:56 00000001000000000000000C
-rw------- 1 postgres postgres 16777216 Jan 13 08:56 00000001000000000000000D
-rw------- 1 postgres postgres 16777216 Jan 13 08:56 00000001000000000000000E
-rw------- 1 postgres postgres       41 Jan 13 08:59 00000002.history
-rw------- 1 postgres postgres 16777216 Jan 13 08:59 00000001000000000000000F.partial
-rw------- 1 postgres postgres 16777216 Jan 13 09:01 00000002000000000000000F
-rw------- 1 postgres postgres 16777216 Jan 13 09:01 000000020000000000000010
-rw------- 1 postgres postgres 16777216 Jan 13 09:01 000000020000000000000011
-rw------- 1 postgres postgres 16777216 Jan 13 09:01 000000020000000000000012
-rw------- 1 postgres postgres 16777216 Jan 13 09:01 000000020000000000000013
-rw------- 1 postgres postgres 16777216 Jan 13 09:02 000000020000000000000014
[postgres@duqk02 pg_wal]$

更多关于 PostgreSQL 系列的学习文章,请参阅:PostgreSQL 数据库,本系列持续更新中。

在原主库上模拟数据变动

* /192.168.13.31/ *
终端1
postgres=# select count(*) from t;
 count 
-------
 50001
(1 row)

postgres=# insert into t select generate_series(1,10000); 
INSERT 0 10000
postgres=# checkpoint;select pg_switch_wal();
CHECKPOINT
 pg_switch_wal 
---------------
 0/F106C98
(1 row)

postgres=# checkpoint;select pg_switch_wal();
CHECKPOINT
 pg_switch_wal 
---------------
 0/100000F0
(1 row)

postgres=# insert into t select generate_series(1,10000); 
INSERT 0 10000
postgres=# checkpoint;select pg_switch_wal();             
CHECKPOINT
 pg_switch_wal 
---------------
 0/11106D88
(1 row)

postgres=# checkpoint;select pg_switch_wal();
CHECKPOINT
 pg_switch_wal 
---------------
 0/120000F0
(1 row)

postgres=# checkpoint;select pg_switch_wal();
CHECKPOINT
 pg_switch_wal 
---------------
 0/130000F0
(1 row)

postgres=# checkpoint;select pg_switch_wal();
CHECKPOINT
 pg_switch_wal 
---------------
 0/140000F0
(1 row)

postgres=# checkpoint;select pg_switch_wal();
CHECKPOINT
 pg_switch_wal 
---------------
 0/150000F0
(1 row)

postgres=# checkpoint;select pg_switch_wal();
CHECKPOINT
 pg_switch_wal 
---------------
 0/16000128
(1 row)

postgres=# checkpoint;select pg_switch_wal();
CHECKPOINT
 pg_switch_wal 
---------------
 0/17000128
(1 row)

postgres=# insert into t select generate_series(1,10000); 
INSERT 0 10000
postgres=# checkpoint;select pg_switch_wal();             
CHECKPOINT
 pg_switch_wal 
---------------
 0/180A4558
(1 row)

postgres=# 

postgres=# select count(*) from t;
 count 
-------
 80001
(1 row)

postgres=#  

终端2
[postgres@duqk01 pg_wal]$ ls -trl
total 180232
-rw------- 1 postgres postgres      338 Sep  7 16:34 000000010000000000000004.00000028.backup
-rw------- 1 postgres postgres 16777216 Jan 13 09:03 00000001000000000000000F
-rw------- 1 postgres postgres 16777216 Jan 13 09:03 000000010000000000000010
-rw------- 1 postgres postgres 16777216 Jan 13 09:03 000000010000000000000011
-rw------- 1 postgres postgres 16777216 Jan 13 09:03 000000010000000000000012
-rw------- 1 postgres postgres 16777216 Jan 13 09:03 000000010000000000000013
-rw------- 1 postgres postgres 16777216 Jan 13 09:03 000000010000000000000014
-rw------- 1 postgres postgres 16777216 Jan 13 09:03 000000010000000000000015
-rw------- 1 postgres postgres 16777216 Jan 13 09:04 000000010000000000000016
-rw------- 1 postgres postgres 16777216 Jan 13 09:04 000000010000000000000017
-rw------- 1 postgres postgres 16777216 Jan 13 09:04 000000010000000000000018
drwx------ 2 postgres postgres     4096 Jan 13 09:04 archive_status
-rw------- 1 postgres postgres 16777216 Jan 13 09:05 000000010000000000000019
[postgres@duqk01 pg_wal]$ ls -trl /data/pgarc/
total 393220
-rw------- 1 postgres postgres 16777216 Sep  7 16:13 000000010000000000000001
-rw------- 1 postgres postgres 16777216 Sep  7 16:29 000000010000000000000002
-rw------- 1 postgres postgres 16777216 Sep  7 16:34 000000010000000000000003
-rw------- 1 postgres postgres 16777216 Sep  7 16:34 000000010000000000000004
-rw------- 1 postgres postgres      338 Sep  7 16:34 000000010000000000000004.00000028.backup
-rw------- 1 postgres postgres 16777216 Sep  7 16:44 000000010000000000000005
-rw------- 1 postgres postgres 16777216 Jan 13 08:56 000000010000000000000006
-rw------- 1 postgres postgres 16777216 Jan 13 08:56 000000010000000000000007
-rw------- 1 postgres postgres 16777216 Jan 13 08:56 000000010000000000000008
-rw------- 1 postgres postgres 16777216 Jan 13 08:56 000000010000000000000009
-rw------- 1 postgres postgres 16777216 Jan 13 08:56 00000001000000000000000A
-rw------- 1 postgres postgres 16777216 Jan 13 08:56 00000001000000000000000B
-rw------- 1 postgres postgres 16777216 Jan 13 08:56 00000001000000000000000C
-rw------- 1 postgres postgres 16777216 Jan 13 08:56 00000001000000000000000D
-rw------- 1 postgres postgres 16777216 Jan 13 08:56 00000001000000000000000E
-rw------- 1 postgres postgres 16777216 Jan 13 09:03 00000001000000000000000F
-rw------- 1 postgres postgres 16777216 Jan 13 09:03 000000010000000000000010
-rw------- 1 postgres postgres 16777216 Jan 13 09:03 000000010000000000000011
-rw------- 1 postgres postgres 16777216 Jan 13 09:03 000000010000000000000012
-rw------- 1 postgres postgres 16777216 Jan 13 09:03 000000010000000000000013
-rw------- 1 postgres postgres 16777216 Jan 13 09:03 000000010000000000000014
-rw------- 1 postgres postgres 16777216 Jan 13 09:03 000000010000000000000015
-rw------- 1 postgres postgres 16777216 Jan 13 09:04 000000010000000000000016
-rw------- 1 postgres postgres 16777216 Jan 13 09:04 000000010000000000000017
-rw------- 1 postgres postgres 16777216 Jan 13 09:04 000000010000000000000018
[postgres@duqk01 pg_wal]$ 

在原主库上修改数据库日志目录的文件和内容:

[postgres@duqk01 ~]$ ll /data/pgdata/pg_log
total 80K
-rw------- 1 postgres postgres  53K Sep  7 16:44 postgresql-2022-09-07.csv
-rw------- 1 postgres postgres 1.0K Sep  7 16:29 postgresql-2022-09-07.log
-rw------- 1 postgres postgres  15K Jan 13 09:04 postgresql-2023-01-13.csv
-rw------- 1 postgres postgres  253 Jan 13 08:54 postgresql-2023-01-13.log
[postgres@duqk01 ~]$ rm -fr /data/pgdata/pg_log/postgresql-2022-09-07*
[postgres@duqk01 ~]$ ll /data/pgdata/pg_log
total 20K
-rw------- 1 postgres postgres 15K Jan 13 09:04 postgresql-2023-01-13.csv
-rw------- 1 postgres postgres 253 Jan 13 08:54 postgresql-2023-01-13.log
[postgres@duqk01 ~]$ vi /data/pgdata/pg_log/postgresql-2023-01-13.log
[postgres@duqk01 ~]$ cat /data/pgdata/pg_log/postgresql-2023-01-13.log
mytest
2023-01-13 08:54:29.538 CST [9878] LOG:  00000: ending log output to stderr
2023-01-13 08:54:29.538 CST [9878] HINT:  Future log output will go to log destination "csvlog".
2023-01-13 08:54:29.538 CST [9878] LOCATION:  PostmasterMain, postmaster.c:1119
[postgres@duqk01 ~]$ 

确认新主库的postgresql.auto.conf 的内容:

 /*192.168.13.32*/ 
[postgres@duqk02 ~]$ cat /data/pgdata/postgresql.auto.conf 
# Do not edit this file manually!
# It will be overwritten by the ALTER SYSTEM command.
primary_conninfo = 'user=replica password=replica channel_binding=prefer host=192.168.13.31 port=1921 sslmode=prefer sslcompression=0 sslsni=1 ssl_min_protocol_version=TLSv1.2 gssencmode=disable krbsrvname=postgres target_session_attrs=any'
[postgres@duqk02 ~]$

对原主库进行pg_rewind. 需要指定 --restore-target-wal -R

 /*192.168.13.31*/ 
[postgres@duqk01 ~]$  pg_ctl stop
waiting for server to shut down.... done
server stopped

[postgres@duqk01 pg_wal]$  pg_rewind --target-pgdata=$PGDATA --source-server='host=192.168.13.32 port=1921 user=postgres password=postgres dbname=postgres' -P
pg_rewind: connected to server
pg_rewind: servers diverged at WAL location 0/F063640 on timeline 1
pg_rewind: error: could not open file "/data/pgdata/pg_wal/00000001000000000000000E": No such file or directory
pg_rewind: fatal: could not find previous WAL record at 0/E0000D8

[postgres@duqk01 ~]$ cat /data/pgdata/postgresql.conf|grep restore
restore_command = 'cp /data/pgarc/%f %p'                # command to use to restore an archived logfile segment
                                # placeholders: %p = path of file to restore
#recovery_target_name = ''      # the named restore point to which recovery will proceed

[postgres@duqk01 ~]$ pg_rewind --target-pgdata=$PGDATA --source-server='host=192.168.13.32 port=1921 user=postgres password=postgres dbname=postgres' -P --restore-target-wal -R
pg_rewind: connected to server
pg_rewind: servers diverged at WAL location 0/F063640 on timeline 1
pg_rewind: rewinding from last common checkpoint at 0/E000060 on timeline 1
pg_rewind: reading source file list
pg_rewind: reading target file list
pg_rewind: reading WAL in target
pg_rewind: need to copy 197 MB (total source directory size is 225 MB)
201937/201937 kB (100%) copied
pg_rewind: creating backup label and updating control file
pg_rewind: syncing target data directory
pg_rewind: Done!
[postgres@duqk01 ~]$ 

pg_rewind之后的验证,/data/pgdata/postgresql.auto.conf 增加了primary_conninfo条目,pg_wal和pg_log目录内容发生变换,从新的主库复制过来的:

* /192.168.13.31/ *

[postgres@duqk01 ~]$ cat /data/pgdata/postgresql.auto.conf 
# Do not edit this file manually!
# It will be overwritten by the ALTER SYSTEM command.
primary_conninfo = 'user=replica password=replica channel_binding=prefer host=192.168.13.31 port=1921 sslmode=prefer sslcompression=0 sslsni=1 ssl_min_protocol_version=TLSv1.2 gssencmode=disable krbsrvname=postgres target_session_attrs=any'
primary_conninfo = 'user=postgres password=postgres channel_binding=prefer host=192.168.13.32 port=1921 sslmode=prefer sslcompression=0 sslsni=1 ssl_min_protocol_version=TLSv1.2 gssencmode=disable krbsrvname=postgres target_session_attrs=any'

[postgres@duqk01 ~]$ ll /data/pgdata/pg_wal/
total 193M
-rw------- 1 postgres postgres 16M Jan 13 09:10 000000020000000000000013
-rw------- 1 postgres postgres 16M Jan 13 09:10 000000020000000000000014
-rw------- 1 postgres postgres 16M Jan 13 09:10 000000020000000000000015
-rw------- 1 postgres postgres 16M Jan 13 09:10 000000020000000000000016
-rw------- 1 postgres postgres 16M Jan 13 09:10 000000020000000000000017
-rw------- 1 postgres postgres 16M Jan 13 09:10 000000020000000000000018
-rw------- 1 postgres postgres 16M Jan 13 09:10 000000020000000000000019
-rw------- 1 postgres postgres 16M Jan 13 09:10 00000002000000000000001A
-rw------- 1 postgres postgres 16M Jan 13 09:10 00000002000000000000001B
-rw------- 1 postgres postgres 16M Jan 13 09:10 00000002000000000000001C
-rw------- 1 postgres postgres 16M Jan 13 09:10 00000002000000000000001D
-rw------- 1 postgres postgres 16M Jan 13 09:10 00000002000000000000001E
-rw------- 1 postgres postgres  41 Jan 13 09:10 00000002.history
drwx------ 2 postgres postgres 109 Jan 13 09:10 archive_status

[postgres@duqk01 ~]$ ll /data/pgdata/pg_log/
total 60K
-rw------- 1 postgres postgres  34K Jan 13 09:10 postgresql-2022-09-07.csv
-rw------- 1 postgres postgres 5.0K Jan 13 09:10 postgresql-2022-09-07.log
-rw------- 1 postgres postgres  12K Jan 13 09:10 postgresql-2023-01-13.csv
-rw------- 1 postgres postgres  823 Jan 13 09:10 postgresql-2023-01-13.log
[postgres@duqk01 ~]$ cat /data/pgdata/pg_log/postgresql-2023-01-13.log
2023-01-13 08:54:34.649 CST [9916] LOG:  00000: ending log output to stderr
2023-01-13 08:54:34.649 CST [9916] HINT:  Future log output will go to log destination "csvlog".
2023-01-13 08:54:34.649 CST [9916] LOCATION:  PostmasterMain, postmaster.c:1119
cp: cannot stat ‘/data/pgarc/00000002.history’: No such file or directory
cp: cannot stat ‘/data/pgarc/000000010000000000000005’: No such file or directory
cp: cannot stat ‘/data/pgarc/00000002.history’: No such file or directory
cp: cannot stat ‘/data/pgarc/00000001000000000000000F’: No such file or directory
cp: cannot stat ‘/data/pgarc/00000001000000000000000F’: No such file or directory
cp: cannot stat ‘/data/pgarc/00000002.history’: No such file or directory
cp: cannot stat ‘/data/pgarc/00000001.history’: No such file or directory
[postgres@duqk01 ~]$ 

新的主库继续模拟数据变化

 /*192.168.13.32*/ 
终端1
postgres=# insert into t select generate_series(1,100);
INSERT 0 100
postgres=# checkpoint;select pg_switch_wal();   
CHECKPOINT
 pg_switch_wal 
---------------
 0/15007E18
(1 row)

postgres=# checkpoint;select pg_switch_wal();   
CHECKPOINT
 pg_switch_wal 
---------------
 0/160000F0
(1 row)

postgres=# checkpoint;select pg_switch_wal();   
CHECKPOINT
 pg_switch_wal 
---------------
 0/170000F0
(1 row)

postgres=# checkpoint;select pg_switch_wal();   
CHECKPOINT
 pg_switch_wal 
---------------
 0/18000128
(1 row)

postgres=# checkpoint;select pg_switch_wal();   
CHECKPOINT
 pg_switch_wal 
---------------
 0/190000F0
(1 row)

postgres=# checkpoint;select pg_switch_wal();   
CHECKPOINT
 pg_switch_wal 
---------------
 0/1A0000F0
(1 row)

postgres=# checkpoint;select pg_switch_wal();   
CHECKPOINT
 pg_switch_wal 
---------------
 0/1B0000F0
(1 row)

postgres=# insert into t select generate_series(1,100);
INSERT 0 100
postgres=# checkpoint;select pg_switch_wal();    
CHECKPOINT
 pg_switch_wal 
---------------
 0/1C003318
(1 row)

postgres=#  

终端2
[postgres@duqk02 pg_wal]$ ls -trl
total 147460
-rw------- 1 postgres postgres       41 Jan 13 08:59 00000002.history
-rw------- 1 postgres postgres 16777216 Jan 13 09:01 00000002000000000000001E
-rw------- 1 postgres postgres 16777216 Jan 13 09:01 00000002000000000000001F
-rw------- 1 postgres postgres 16777216 Jan 13 09:14 000000020000000000000020
-rw------- 1 postgres postgres 16777216 Jan 13 09:14 000000020000000000000021
-rw------- 1 postgres postgres 16777216 Jan 13 09:14 000000020000000000000022
-rw------- 1 postgres postgres 16777216 Jan 13 09:14 00000002000000000000001A
-rw------- 1 postgres postgres 16777216 Jan 13 09:14 00000002000000000000001B
-rw------- 1 postgres postgres 16777216 Jan 13 09:14 00000002000000000000001C
drwx------ 2 postgres postgres      146 Jan 13 09:14 archive_status
-rw------- 1 postgres postgres 16777216 Jan 13 09:15 00000002000000000000001D
[postgres@duqk02 pg_wal]$ ls -trl /data/pgarc/
total 393220
-rw------- 1 postgres postgres 16777216 Jan 13 08:56 000000010000000000000006
-rw------- 1 postgres postgres 16777216 Jan 13 08:56 000000010000000000000007
-rw------- 1 postgres postgres 16777216 Jan 13 08:56 000000010000000000000008
-rw------- 1 postgres postgres 16777216 Jan 13 08:56 000000010000000000000009
-rw------- 1 postgres postgres 16777216 Jan 13 08:56 00000001000000000000000A
-rw------- 1 postgres postgres 16777216 Jan 13 08:56 00000001000000000000000B
-rw------- 1 postgres postgres 16777216 Jan 13 08:56 00000001000000000000000C
-rw------- 1 postgres postgres 16777216 Jan 13 08:56 00000001000000000000000D
-rw------- 1 postgres postgres 16777216 Jan 13 08:56 00000001000000000000000E
-rw------- 1 postgres postgres       41 Jan 13 08:59 00000002.history
-rw------- 1 postgres postgres 16777216 Jan 13 08:59 00000001000000000000000F.partial
-rw------- 1 postgres postgres 16777216 Jan 13 09:01 00000002000000000000000F
-rw------- 1 postgres postgres 16777216 Jan 13 09:01 000000020000000000000010
-rw------- 1 postgres postgres 16777216 Jan 13 09:01 000000020000000000000011
-rw------- 1 postgres postgres 16777216 Jan 13 09:01 000000020000000000000012
-rw------- 1 postgres postgres 16777216 Jan 13 09:01 000000020000000000000013
-rw------- 1 postgres postgres 16777216 Jan 13 09:02 000000020000000000000014
-rw------- 1 postgres postgres 16777216 Jan 13 09:14 000000020000000000000015
-rw------- 1 postgres postgres 16777216 Jan 13 09:14 000000020000000000000016
-rw------- 1 postgres postgres 16777216 Jan 13 09:14 000000020000000000000017
-rw------- 1 postgres postgres 16777216 Jan 13 09:14 000000020000000000000018
-rw------- 1 postgres postgres 16777216 Jan 13 09:14 000000020000000000000019
-rw------- 1 postgres postgres 16777216 Jan 13 09:14 00000002000000000000001A
-rw------- 1 postgres postgres 16777216 Jan 13 09:14 00000002000000000000001B
-rw------- 1 postgres postgres 16777216 Jan 13 09:14 00000002000000000000001C
[postgres@duqk02 pg_wal]$ 

新主库添加pg_hba条目:

* /192.168.13.32/ *
[postgres@duqk02 pg_wal]$ vi /data/pgdata/pg_hba.conf 
增加
host    replication     all     192.168.13.31/32        md5
host    replication     all     192.168.13.32/32        md5
[postgres@duqk02 pg_wal]$ pg_ctl reload
server signaled
[postgres@duqk02 pg_wal]$ 

原主库启动数据库

 /*192.168.13.31*/ 

[postgres@duqk01 ~]$ touch /data/pgdata/standby.signal

[postgres@duqk01 ~]$ pg_ctl start
waiting for server to start....2023-01-13 09:22:14.949 CST [10085] LOG:  00000: redirecting log output to logging collector process
2023-01-13 09:22:14.949 CST [10085] HINT:  Future log output will appear in directory "pg_log".
2023-01-13 09:22:14.949 CST [10085] LOCATION:  SysLogger_Start, syslogger.c:674
............................ stopped waiting
pg_ctl: could not start server
Examine the log output.

数据库日志:

2023-01-13 09:22:14.949 CST,,,10085,,63c0b246.2765,1,,2023-01-13 09:22:14 CST,,0,LOG,00000,"ending log output to stderr",,"Future log output will go to log destination ""csvlog"".",,,,,,"PostmasterMain, postmaster.c:1119","","postmaster",,0
2023-01-13 09:22:14.949 CST,,,10085,,63c0b246.2765,2,,2023-01-13 09:22:14 CST,,0,LOG,00000,"starting PostgreSQL 14.5 on x86_64-pc-linux-gnu, compiled by gcc (GCC) 4.8.5 20150623 (Red Hat 4.8.5-44), 64-bit",,,,,,,,"PostmasterMain, postmaster.c:1129","","postmaster",,0
2023-01-13 09:22:14.949 CST,,,10085,,63c0b246.2765,3,,2023-01-13 09:22:14 CST,,0,LOG,00000,"listening on IPv4 address ""0.0.0.0"", port 1921",,,,,,,,"StreamServerPort, pqcomm.c:585","","postmaster",,0
2023-01-13 09:22:14.949 CST,,,10085,,63c0b246.2765,4,,2023-01-13 09:22:14 CST,,0,LOG,00000,"listening on IPv6 address ""::"", port 1921",,,,,,,,"StreamServerPort, pqcomm.c:585","","postmaster",,0
2023-01-13 09:22:14.950 CST,,,10085,,63c0b246.2765,5,,2023-01-13 09:22:14 CST,,0,LOG,00000,"listening on Unix socket ""./.s.PGSQL.1921""",,,,,,,,"StreamServerPort, pqcomm.c:579","","postmaster",,0
2023-01-13 09:22:14.954 CST,,,10087,,63c0b246.2767,1,,2023-01-13 09:22:14 CST,,0,LOG,00000,"database system was interrupted while in recovery at log time 2023-01-13 09:07:01 CST",,"If this has occurred more than once some data might be corrupted and you might need to choose an earlier recovery target.",,,,,,"StartupXLOG, xlog.c:6570","","startup",,0
2023-01-13 09:22:14.969 CST,,,10087,,63c0b246.2767,2,,2023-01-13 09:22:14 CST,,0,LOG,00000,"entering standby mode",,,,,,,,"StartupXLOG, xlog.c:6638","","startup",,0
2023-01-13 09:22:15.253 CST,,,10087,,63c0b246.2767,3,,2023-01-13 09:22:14 CST,,0,LOG,00000,"restored log file ""00000001000000000000000E"" from archive",,,,,,,,"RestoreArchivedFile, xlogarchive.c:215","","startup",,0
2023-01-13 09:22:15.273 CST,,,10087,,63c0b246.2767,4,,2023-01-13 09:22:14 CST,1/0,0,LOG,00000,"redo starts at 0/E000028",,,,,,,,"StartupXLOG, xlog.c:7378","","startup",,0
2023-01-13 09:22:15.733 CST,,,10087,,63c0b246.2767,5,,2023-01-13 09:22:14 CST,1/0,0,LOG,00000,"restored log file ""00000001000000000000000F"" from archive",,,,,,,,"RestoreArchivedFile, xlogarchive.c:215","","startup",,0
2023-01-13 09:22:16.178 CST,,,10087,,63c0b246.2767,6,,2023-01-13 09:22:14 CST,1/0,0,LOG,00000,"restored log file ""000000010000000000000010"" from archive",,,,,,,,"RestoreArchivedFile, xlogarchive.c:215","","startup",,0
2023-01-13 09:22:16.613 CST,,,10087,,63c0b246.2767,7,,2023-01-13 09:22:14 CST,1/0,0,LOG,00000,"restored log file ""000000010000000000000011"" from archive",,,,,,,,"RestoreArchivedFile, xlogarchive.c:215","","startup",,0
2023-01-13 09:22:17.221 CST,,,10087,,63c0b246.2767,8,,2023-01-13 09:22:14 CST,1/0,0,LOG,00000,"restored log file ""000000010000000000000012"" from archive",,,,,,,,"RestoreArchivedFile, xlogarchive.c:215","","startup",,0
2023-01-13 09:22:17.276 CST,,,10087,,63c0b246.2767,9,,2023-01-13 09:22:14 CST,1/0,0,PANIC,XX000,"unexpected timeline ID 2 (should be 1) in checkpoint record",,,,,"WAL redo at 0/13000060 for XLOG/CHECKPOINT_ONLINE: redo 0/13000028; tli 2; prev tli 2; fpw true; xid 0:757; oid 32774; multi 1; offset 0; oldest xid 727 in DB 1; oldest multi 1 in DB 1; oldest/newest commit timestamp xid: 0/0; oldest running xid 757; online",,,"xlog_redo, xlog.c:10490","","startup",,0
2023-01-13 09:22:43.677 CST,,,10085,,63c0b246.2765,6,,2023-01-13 09:22:14 CST,,0,LOG,00000,"startup process (PID 10087) was terminated by signal 6: Aborted",,,,,,,,"LogChildExit, postmaster.c:3759","","postmaster",,0
2023-01-13 09:22:43.677 CST,,,10085,,63c0b246.2765,7,,2023-01-13 09:22:14 CST,,0,LOG,00000,"terminating any other active server processes",,,,,,,,"HandleChildCrash, postmaster.c:3482","","postmaster",,0
2023-01-13 09:22:43.677 CST,,,10085,,63c0b246.2765,8,,2023-01-13 09:22:14 CST,,0,LOG,00000,"shutting down due to startup process failure",,,,,,,,"PostmasterStateMachine, postmaster.c:4020","","postmaster",,0
2023-01-13 09:22:43.779 CST,,,10085,,63c0b246.2765,9,,2023-01-13 09:22:14 CST,,0,LOG,00000,"database system is shut down",,,,,,,,"UnlinkLockFiles, miscinit.c:963","","postmaster",,0

由于此时原主库的restore_command是指向本地的归档,应用不到新主库的归档,所以得修改restore_command指向新的主库归档,前提是节点之间做好互信。

 /*192.168.13.31*/ 

[postgres@duqk01 ~]$ cat /data/pgdata/postgresql.conf |grep restore
restore_command = 'cp /data/pgarc/%f %p'                # command to use to restore an archived logfile segment
                                # placeholders: %p = path of file to restore
#recovery_target_name = ''      # the named restore point to which recovery will proceed
[postgres@duqk01 ~]$ 

[postgres@duqk01 ~]$ vi /data/pgdata/postgresql.conf               
[postgres@duqk01 ~]$ cat /data/pgdata/postgresql.conf |grep restore
restore_command = 'scp 192.168.13.32:/data/pgarc/%f %p'          # command to use to restore an archived logfile segment
                                # placeholders: %p = path of file to restore
#recovery_target_name = ''      # the named restore point to which recovery will proceed
[postgres@duqk01 ~]$ 
----先设置好节点间的互信

[postgres@duqk01 ~]$ pg_ctl start
waiting for server to start....2023-01-13 09:24:05.990 CST [10118] LOG:  00000: redirecting log output to logging collector process
2023-01-13 09:24:05.990 CST [10118] HINT:  Future log output will appear in directory "pg_log".
2023-01-13 09:24:05.990 CST [10118] LOCATION:  SysLogger_Start, syslogger.c:674
.... done
server started
[postgres@duqk01 ~]$ 

[postgres@duqk01 ~]$ psql
psql (14.5)
Type "help" for help.

postgres=# select count(*) from t;
 count 
-------
   500
(1 row)

postgres=# 

在新的主库上查看流复制状态

 /*192.168.13.32*/ 

postgres=# select * from pg_replication_slots\gx
-[ RECORD 1 ]-------+-----------
slot_name           | rep
plugin              | 
slot_type           | physical
datoid              | 
database            | 
temporary           | f
active              | t
active_pid          | 10518
xmin                | 763
catalog_xmin        | 
restart_lsn         | 0/1D003820
confirmed_flush_lsn | 
wal_status          | reserved
safe_wal_size       | 
two_phase           | f

postgres=# select * from pg_replication_slots\gx
-[ RECORD 1 ]-------+-----------
slot_name           | rep
plugin              | 
slot_type           | physical
datoid              | 
database            | 
temporary           | f
active              | t
active_pid          | 10518
xmin                | 763
catalog_xmin        | 
restart_lsn         | 0/1D003820
confirmed_flush_lsn | 
wal_status          | reserved
safe_wal_size       | 
two_phase           | f

postgres=#  

结论

1.结合pg_rewind的原理,验证了pg_rewind后,原主库除了数据块和新的主库一致之外,原主库的wal日志,数据库日志,$PGDATA下的配置文件等,都是从新的主库拉取。

2.对于设置为archive_mode为always模式的流复制环境,在原主库做pg_rewind的时候,是需要本机的归档的。如果pg_rewind成功后,在启动原主库的时候,是需要新的主库的归档。

更多关于 PostgreSQL 系列的学习文章,请参阅:PostgreSQL 数据库,本系列持续更新中。

PostgreSQL数据恢复利器pg_rewind详解 WAL(Write-Ahead Logging)是PostgreSQL实现数据持久化和高可用的核心技术,通过预写日志机制确保数据安全。pg_rewind基于WAL日志分析实现增量恢复,大幅提升数据库灾备效率。该工具通过对比源库和目标库的WAL历史,智能识别数据分叉点,仅同步差异部分,将传统全量恢复耗时从数小时缩短至分钟级。在数据库主备切换、脑裂恢复等场景中表现优异,特别适合与流复制架构配合使用。PostgreSQL 12版本后,pg_rewind结合并行复制和WAL压缩技术,可进一步提升大规模数据库的恢复速 阅读详情

相关推荐

PostgreSQL data同步工具【pg_rewind】

pg_rewind is a tool for synchronizing a PostgreSQL data directory with another PostgreSQL data directory that was forked from the first one. The result is equivalent to rsyncing the first data directory with the second one. The advantage of pg_rewind over

连顺科 4308

pg_rewind详解

什么是pg_rewind? pg_rewind是pg提供的工具,当2个pg实例时间线(timeline)出现分叉时,pg_rewind可以做实例间的同步。(比如主库运行的情况下,备库failover后运行了一段时间,此时主备的时间线就出现了分叉) pg_rewind会对比两者的大小,然后把大小不一样的文件从源拷贝到目标,包括配置文件。但是它不会对比没有发生改变的文件,所以pg_rewind在比较大的库,更改少量数据时,运行效率较高。 pg_rewind可以运用在备库failover后,备库即时运行一段时间

liuzhilong的博客 6181

利用OGG实现PostgreSQL实时同步

本文详细阐述了利用OGG实现PostgreSQL实时同步的全过程。

IT邦德 2678

PostgreSQL数据库数据同步——pg_rewind概念

pg的高可用架构中,主库挂掉后,备库会自动升级为主库继续提供服务,对于原来的主库通常有两种处理方式: 删掉,重搭新备库。 降级为备库,继续服务。 很显然,相比来说第一种不是个很好的方案,而且当数据量比较大时,重搭备库的时间成本太高。 但是因为老的主库挂掉的原因多种多样,甚至有可能是高可用系统的误判,而老主库也有可能是在挂掉之后又重新作为主库启动起来,这个时候降级并重搭流复制关系的操作就有可能失败(新的备库比新主库数据更超前)。为了解决这种情况,PostgreSQL 引入了pg_rewind工具。 pg_

肥叔菌的博客 3293

STM32F401RET6寄存器手册阅读标记

对于时钟树配置,可参考STM32CubeMX中的时钟树配置,STM32CubeMX将基础配置图像化,较为简单。RCC_CR寄存器的HSIRDY位为只读位,当读取值为1时,表示HSI振荡器准备就绪,当HSION位被设置时,HSIRDY会自动设置为低电平。//问题标记:USART配置寄存器信息是如何与USART1/2/3建立联系的(为什么不是三个分别配置)查阅寄存器手册可知,需要配置时钟的模块有:USART1,IO port A。(2)TX配置方法(寄存器手册512页)(4)配置寄存器(寄存器手册548页)

m0_72615170的博客 1468

proteus仿真51单片机操作指南:串口通信仿真配置详解

深入讲解如何在proteus仿真51单片机中实现串口通信,涵盖虚拟串口设置、电路连接与调试技巧,帮助开发者高效完成通信仿真验证。

weixin_36197669的博客 570

PostgreSQL数据库关于pg_rewind的认识

pg_rewind是PostgreSQL提供的一个工具,用于在主备库时间线出现分叉时进行同步。它通过比较文件差异,仅同步不一致的文件,效率较高。使用前需配置源库pg_hba.conf并确保目标库开启wal_log_hints参数。执行过程中会复制差异文件和WAL日志,但若WAL丢失则需手动恢复。常见问题包括权限不足、连接配置错误等,需使用高权限用户并正确配置参数。使用前建议备份目标库,以防rewind失败导致数据损坏。该工具适用于主备切换后重新同步老主库的场景。

Auspicious航的博客 789

从DWS到设备树:MTK平台LK阶段GPIO初始化的隐秘路径与调试实战

本文深入探讨了MTK平台LK阶段GPIO初始化的完整流程,揭示了从DWS配置到设备树生成的隐秘转换路径。通过分析MT6768等平台的启动框架,提供了针对preloader到LK阶段GPIO初始化异常的实战调试方法与最佳实践,帮助开发者有效解决硬件与软件配置不匹配的常见问题。

h9j8k7l6m5n的博客 1003

postgresql下pg_rewind数据库恢复

在 PostgreSQL 主备切换(Failover)后,旧的主库因为数据可能领先或与新主库(原备库)产生了分歧,无法直接启动同步。pg_rewind 的作用是对比两者的 WAL 日志,将旧主库“回滚”到分叉点,使其能够以增量同步的方式重新加入集群,避免了全量重做数据(pg_basebackup)的巨大开销。将从新主库拷贝过来的“正确”数据页,直接写入到旧主库对应的文件位置中。最后,它会从新主库拷贝分叉点之后的所有 WAL 日志到旧主库的。一旦确定了旧主库中哪些块是“脏”的(即分叉后修改过的),

king_harry的专栏 1054

从零到一:TI AWR1843 Boost EVM与DCA1000 EVM的ADC数据采集实战指南

本文详细介绍了TI AWR1843 Boost EVM与DCA1000 EVM的ADC数据采集实战指南,涵盖硬件连接、软件配置、固件烧录、雷达参数设置及数据处理等关键步骤。通过MATLAB等工具,开发者可高效实现毫米波雷达数据采集,适用于自动驾驶、工业检测等领域。

weixin_29001327的博客 966

Shader之——花草动画shader

今天 ,接到了个需求,花草的动画。谈到花草动画,立马就想到顶点动画,让顶点动起来就可以实现了。但是有个问题,所有的草都往一个方向运动,这个就麻烦了。因为在shader里没有随机这种概念,提到最多的是用一张噪声图来模拟。在网上搜索了一下,发现有更好的办法,就是用每个顶点到一个点的距离来控制动画的开始,毕竟每个顶点到同一个点的距离很少是一样的。 float dis = distance ...

baicaishisan的博客 2183

Postgresql PG_REWIND 怎么就这样不行

PostgreSQL 在操作的过程中,如果利用物理复制的过程中,另一台从库,或者主库由于某些原因,不再与主库同步,或者主库crash 起不来了,怎么办,如果在利用现在的主库或备库,弄出一...

sql server的专栏 950

PowerPMAC配置EtherCAT设备

本文详细介绍了在PowerPMAC IDE环境下配置EtherCAT伺服电机的完整流程。主要内容包括:准备工作(连接硬件和获取ESI文件)、通过ESI管理器加载配置文件、网络扫描识别从站设备、变量映射(定义输入输出位置参数)、激活EtherCAT通讯(验证状态字和实际位置)以及相关参数说明。文章还概述了主站配置的8个方面和从站配置的7个选项,重点说明了PDO映射和变量分配机制,为伺服电机的EtherCAT通信配置提供了系统指导。

mahuliang321的博客 968

推荐使用pg_rewind:高效的数据目录同步工具

推荐使用pg_rewind:高效的数据目录同步工具 1、项目介绍 pg_rewind 是一个专为 PostgreSQL 数据库设计的工具,用于将一个数据目录(旧集群)与从它派生出的另一个数据目录(新集群)进行同步。该工具的优势在于,它利用WAL(Write-Ahead Log)记录来确定改变的数据块,而无需逐个文件读取整个集群,这在大数据量且仅小部分数据有差异的场景下,大大提高了同步效率。 注意:...

gitblog_00005的博客 585

Vue - 超强实现网页禁止浏览器缩放功能,浏览器缩放时保持网页不变形、元素不会被挤压等,屏蔽浏览器鼠标滚轮缩放页面(提供详细示例代码,一次引入整个网站无人可以搞乱你的页面布局及样式)

vue,nuxt,禁止浏览器缩放,如何用户缩放浏览器导致页面变形,网页缩放后页面变形了怎么办,怎么解决网站被缩放后元素乱套错乱,vue怎么禁止网页不被缩放,vue如何禁止浏览器缩放,vue缩放网页变形影响布局怎么办,vue电脑分辨率及缩放导致页面变形的问题,前端页面解决浏览器或者系统被放大和缩小导致的显示问题,Vue中页面自适应缩放,如何防止Vue页面缩放时变形/调整大小,Vue项目中,防止页面被缩放和放大,vue等比例缩放网页,网页缩放后界面变形咋办,禁止页面缩放,vue禁止浏览器改变窗口大小,Vue项目

🏆 前端领域优质创作者 1万+

Open3D KD-tree的使用【2025最新版】

Open3d使用FLANN构建KDTree以便进行快速最近邻检索。博客长期更新,本文最近一次更新时间为:2025年1月1日,代码已同步更新至Open3D 0.18.0版本。

点云侠的博客 40万+

pg_rewind的使用

pg_rewind 是postgresql主丛数据库之同步数据目录的工具。需要目标服务器在postgresql.conf 中允许wal_log_hints,或者在 initdb初始化集群时允许 ch...

couxue8573的博客 2618

Devexpress16.2.6破解工具

Devexpress16.2.6破解工具Devexpress16.2.6破解工具Devexpress16.2.6破解工具Devexpress16.2.6破解工具

PostgreSQL下pg_rewind的使用

流复制,pg_rewind,promote

duqk1982的博客 1341

RU DOS版、EFI版32bit/64bit BIOS常用工具

DOS版、EFI版的RU工具,可用来查看IO、MEM、PCI、SMBIOS等资源。亲测在EFI SHELL下可用。

最新的sdio 4.0 spec 协议标准 带书签 高清完整PDF版

Part-E1-SDIO-Specification-Ver4.00-Final-120220.pdf:最新的sdio 4.0 spec 协议标准 带书签 高清完整PDF版,包括SDIO 接口的外设,SDIO 接口官方协议等。

pg_rewind

pg_rewind 作者:瀚高PG实验室(Highgo PG Lab)-Chrisx reference pg_rewind 文章目录pg_rewind1. 优点2. 使用要求3. 工作原理4. 使用示例 pg_rewind是一个工具,用于在群集的时间线出现分歧后,将 PostgreSQL 群集与同一群集的另一个副本进行同步。 典型的案例是旧主服务器在故障转移后重新联机,将其作为新主机之后的备用服务器。 1. 优点 pg_rewind成功后,目标数据目录的状态类似于源数据目录的基本备份(作者注,数据一致

HighGO 1627

OV9734 DATASHEET,完整规格书

OV9734完整规格书,包括电气参数,尺寸规格,寄存器配置表等

PostgreSql pg_rewind

一、概述 pg_rewind 是 postgresql 主从数据库之同步数据目录的工具。 pg_rewind 相比 pg_basebackup 和 rsync 这样的工具来说,优势是它不需要从源目录拷贝所有的数据文件,而是会对比时间线发生偏离的点,只拷贝变化过的文件,这样对于数据量很大的情况下速度更快。 pg_rewind 使用前提:需要目标服务器在 postgresql.conf 中允许 wal_log_hints(默认 off),或者在 initdb 初始化数据库时启用数据校验(–data-checks

脑子进水养啥鱼?的博客 1120

【无标题】为什么 pg_rewind 在 PostgreSQL 中很重要?

pg_rewind是 PostgreSQL 中的一个实用程序,用于将一个数据库集群与另一个数据库集群同步,通常是在故障转移或主服务器和备用服务器角色切换之后。当旧主服务器需要在故障转移后作为备用服务器重新加入新的主服务器时,它特别有用。

weixin_43230594的博客 1054

pg_rewind到底能做什么?

我们知道postgresql的主从切换有点麻烦,或者说操作步骤要求很严格。可能我们经常遇到这种情况,在没有将主库杀死的情况下将备库提升为主,这时主备库可能由于某种原因都在提供写入操作,这时发生脑裂,如果不考虑数据丢失因素,这时我们可能想将原来的主库以备库的模式重新加入集群,但是主备库此时的时间线已经偏离了,这时就需要我们的pg_rewind工具了。 pg_rewind相比pg_basebackup...

数据库架构之美 1934

postgresql pg_rewind 类似oracle的flashback+基于scn的恢复

流复制主备数据库间数据目录同步工具。仅复制产生变化的数据块和一些文件:新数据文件、配置文件、WAL segments。pg_rewind检查源和目标集群的时间线历史以确定它们的分歧点,并在目标集群的pg_wal目录中找到WAL,一直到达分歧点。分歧点可以在目标时间线、源时间线或它们的共同祖先上找到。在典型的故障转移场景中,目标集群在产生分歧后很快被关闭,这不是问题,但如果目标集群在生生分歧后运行很长时间,它的旧WAL文件可能不再存在。

jnrjian的博客 810

pg_rewind增量同步备库

/* 在数据库变得比较大时, 例如上TB, 如果部署了PostgreSQL primary-standby 流复制或者log shipping HA. 当发生了failover, old primary节点可能因为某些原因需要重新同步数据.  在广域网上, 由于网络异常也可能造成standby节点落后主节点, 导致需要重新同步数据. 小数据库重新同步数据很方便, 全量或者使用rsync增量

rudy gao 3890
上一篇: 进阶数据库系列(二十六):PostgreSQL 数据库监控管理
下一篇: 进阶数据库系列(十七):PostgreSQL 基于 Patroni 高可用架构部署及故障切换
pgdba
博客等级 码龄4年 30粉丝 31原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值