案例演示:fosync功能,
在PG主备流复制
中,如果主库发生故障,备库提升为新的主库,在异步主备
的情况下,可能会有一些事务停留在了主库,没有同步到备库。这样会导致一些数据丢失。目前可以使用walminer
解析出延迟同步的数据,然后将数据在新主库再执行一遍这样的操作,来完成丢失数据的找回。
效果与pg_rewind相当
注意:实验思想是,先构建主备库同步,然后在主库开启一个事务,在这个事务未完成的这个时间段去把备库升主,然后再提交事务,最后确认新主库的提升wal检查点位置去执行fosync操作,最后根据产生的undo sql语句去完成老主库未同步过去的DML操作。
建议实验walminer版本:https://gitee.com/movead/XLogMiner/releases/download/walminer_dev_4.6.0_20240306/walminer_x86_64_centos_v4.6.0.tar.gz
walminer的安装步骤建议参考我之前的文章:https://blog.csdn.net/qq_61920297/article/details/140838936?spm=1001.2014.3001.5501
fosync帮助文档
lchch@deepin:/usr/local/walminer$ walminer help
#################################################
Walminer for PostgreSQL wal
Vip License for Movead
#################################################
walminer [command] [options]
COMMANDS
---------
.................此处省略............
#fosync
options
-D dic file for miner
-w wal file path to miner
-t dest of miner result(1 stdout, 2 file, 3 db, 4 apply)(stdout default)
-f file to store miner result if t = 2
-l lsn it start fync
-d target database name if t=3(default postgres)
-h target database host if t=3(default localhost)
-p target database port if t=3(default 5432)
-u target database user if t=3(default postgres)
-W target user password if t=3
#################################################
根据您的要求,以下是一个表格,包含了您提供的参数及其说明:
参数 | 说明 |
---|---|
-D | 指定主库的数据字典 |
-w | 指定主库WAL文件目录 |
-t | 指定解析结果的输出方式:指定解析结果的输出方式: 1.输出到标准输出; 2.输出到文件; 3.输出到某个数据库,以便分析fo内容 ; 4.直接将解析结果apply到新主库 |
-f | 当-t=2 时,指定输出文件的路径 |
-l | 指定备库提升时的LSN点 |
-d | 新主库的数据库名(作为数据库连接字符串的一部分) |
-h | 新主库的主机名或IP地址(作为数据库连接字符串的一部分) |
-p | 新主库的端口号(作为数据库连接字符串的一部分) |
-u | 新主库的用户名(作为数据库连接字符串的一部分) |
-W | 新主库的密码(作为数据库连接字符串的一部分,出于安全考虑,建议避免在命令行中直接显示密码) |
4.1、布置数据场景
## 给主库上的表格修改一些数据
[fbase@postgres pg_wal]$ psql
psql (16.3)
Type "help" for help.
postgres=# \d
List of relations
Schema | Name | Type | Owner
--------+-------------+-------+-------
public | test_fosync | table | fbase
(1 row)
postgres=# select * from test_fosync ;
i
---
1
2
3
4
5
6
7
(7 rows)
postgres=# delete from test_fosync where i = 7;
DELETE 1
postgres=# select * from test_fosync ;
i
---
1
2
3
4
5
6
(6 rows)
##从此处开始向上,主备库同步
postgres=# begin;
BEGIN
postgres=*# delete from test_fosync where i = 6;
DELETE 1
##从这里开始去把备库给升主
postgres=*# delete from test_fosync where i = 5;
DELETE 1
postgres=*# commit;
COMMIT
#提交完事务后再执行一段时间DML语句
postgres=# select * from test_fosync ;
i
---
1
2
3
4
(4 rows)
postgres=# delete from test_fosync where i = 4;
DELETE 1
postgres=# delete from test_fosync where i = 3;
DELETE 1
postgres=# select * from test_fosync ;
i
---
1
2
(2 rows)
postgres=# \q
[fbase@postgres pg_wal]$ cd
## 在备库上,查看数据
postgres=# \d
List of relations
Schema | Name | Type | Owner
--------+-------------+-------+-------
public | test_fosync | table | fbase
(1 row)
postgres=# select * from test_fosync
;
i
---
1
2
3
4
5
6
(6 rows)
4.2、备库升主库,执行fosync功能
## 备库升主库,查看新主库wal日志信息
[fbase@postgres ~]$ pg_ctl promote
waiting for server to promote.... done
server promoted
[fbase@postgres ~]$ psql
psql (16.3)
Type "help" for help.
postgres=# \q
[fbase@postgres ~]$ cd $PGDATA
[fbase@postgres fbdata]$ ls
backup_label.old pg_commit_ts pg_notify pg_subtrans postgresql.auto.conf
backup_manifest pg_dynshmem pg_replslot pg_tblspc postgresql.conf
base pg_hba.conf pg_serial pg_twophase postgresql.conf.backup
current_logfiles pg_ident.conf pg_snapshots PG_VERSION postmaster.opts
global pg_logical pg_stat pg_wal postmaster.pid
log pg_multixact pg_stat_tmp pg_xact
[fbase@postgres fbdata]$ cd pg_wal/
## 00000002.history代表数据库提升后数据库的时间线为2。实际操作时要选择时间线最大的history文件
[fbase@postgres pg_wal]$ ls
000000010000000000000002 000000020000000000000003 archive_status
000000010000000000000003.partial 00000002.history
##下面0/300A460表示从0/300A460位置备库提升为了新主库。在下面的fosync操作中就需要0/300A460这个值。
[fbase@postgres pg_wal]$ cat 00000002.history
1 0/6000218 no recovery target specified
执行fosync功能
#生成新的字典数据
[fbase@postgres bin]$ walminer builtdic -D ~/walminer.dic -f -h localhost -p 8432 -u fbase
#################################################
Walminer for PostgreSQL wal
Contact Author by mail 'lchch1990@sina.cn'
No License for walminer test, for get a license you can read:
https://gitee.com/movead/XLogMiner/wikis/walminer%20license
#################################################
DIC INFO#
sysid:7398075683162685763 timeline:1 dbversion:160003 walminer:4.6
#执行fosync
[fbase@postgres bin]$ walminer fosync -D ~/walminer.dic -w /data/fbase/fbdata/pg_wal/ -u fbase -p 8432 -t 3 -l 0/6000218 -h 192.168.6.108 -W fbase
#################################################
Walminer for PostgreSQL wal
Contact Author by mail 'lchch1990@sina.cn'
No License for walminer test, for get a license you can read:
https://gitee.com/movead/XLogMiner/wikis/walminer%20license
#################################################
NOTICE: table "walminer_contents" does not exist, skipping
Switch wal to /data/fbase/fbdata/pg_wal//000000010000000000000006 on time 2024-08-01 17:10:45.685189+08
Switch wal to /data/fbase/fbdata/pg_wal//000000010000000000000001 on time 2024-08-01 17:10:45.685325+08
Switch wal to /data/fbase/fbdata/pg_wal//000000010000000000000002 on time 2024-08-01 17:10:45.69206+08
Switch wal to /data/fbase/fbdata/pg_wal//000000010000000000000003 on time 2024-08-01 17:10:45.692079+08
Switch wal to /data/fbase/fbdata/pg_wal//000000010000000000000004 on time 2024-08-01 17:10:45.692121+08
Switch wal to /data/fbase/fbdata/pg_wal//000000010000000000000005 on time 2024-08-01 17:10:45.692136+08
Switch wal to /data/fbase/fbdata/pg_wal//000000010000000000000006 on time 2024-08-01 17:10:45.692143+08
Get start lsn 0/60001a8 for xid range
Get end lsn 0/60003f8 for xid range
Switch wal to /data/fbase/fbdata/pg_wal//000000010000000000000001 on time 2024-08-01 17:10:45.692158+08
Switch wal to /data/fbase/fbdata/pg_wal//000000010000000000000002 on time 2024-08-01 17:10:45.698083+08
Switch wal to /data/fbase/fbdata/pg_wal//000000010000000000000003 on time 2024-08-01 17:10:45.698102+08
Switch wal to /data/fbase/fbdata/pg_wal//000000010000000000000004 on time 2024-08-01 17:10:45.69814+08
Switch wal to /data/fbase/fbdata/pg_wal//000000010000000000000005 on time 2024-08-01 17:10:45.698148+08
Switch wal to /data/fbase/fbdata/pg_wal//000000010000000000000006 on time 2024-08-01 17:10:45.698155+08
Switch wal to /data/fbase/fbdata/pg_wal//000000010000000000000005 on time 2024-08-01 17:10:45.698163+08
Switch wal to /data/fbase/fbdata/pg_wal//000000010000000000000006 on time 2024-08-01 17:10:45.698181+08
[fbase@postgres bin]$
参数 | 说明 |
---|---|
-D | 指定主库的数据字典 |
-w | 指定主库WAL文件目录 |
-t | 4.直接将解析结果apply到新主库 |
-l | 指定备库提升时的LSN点 |
-d | 新主库的数据库名(作为数据库连接字符串的一部分) |
-h | 新主库的主机名或IP地址(作为数据库连接字符串的一部分) |
-p | 新主库的端口号(作为数据库连接字符串的一部分) |
-u | 新主库的用户名(作为数据库连接字符串的一部分) |
-W | 新主库的密码 |
4.3、fosync操作完成后查询新主库数据
然后使用walminer_contents表中的undosql去完成之前老主库
未完同步过去的DML操作
postgres=# \d+
List of relations
Schema | Name | Type | Owner | Persistence | Access method | Size | Description
--------+-------------------+-------+-------+-------------+---------------+------------+-------------
public | test_fosync | table | fbase | permanent | heap | 8192 bytes |
public | walminer_contents | table | fbase | unlogged | heap | 24 kB |
(2 rows)
![
](image-1.png)
然后使用walminer_contents表中的undosql去完成之前`老主库`未完同步过去的DML操作
postgres=# \x
Expanded display is on.
postgres=# SELECT * FROM walminer_contents LIMIT 1;
-[ RECORD 1 ]-------------------------------------------
sqlno | 1
xid | 754
topxid | 0
database | postgres
sqlkind |
minerd | t
timestamp | 2024-08-01 17:07:23.28175+08
op_text | DELETE FROM public.test_fosync WHERE i=6
undo_text | INSERT INTO public.test_fosync(i) VALUES(6)
complete | t
relation | test_fosync
start_lsn | 0/60001A8
commit_lsn | 0/6000288
postgres=#
字段名 | 描述 |
---|---|
sqlno | 序号,可能用于记录或标识操作的顺序或顺序号 |
xid | 事务 ID,标识执行该操作的事务的唯一标识符 |
topxid | 最顶层事务的 ID,通常在 PostgreSQL 中表示最高级别事务的 ID |
database | 数据库名称,指示操作发生在哪个数据库中 |
sqlkind | SQL 类型,可能指示操作的类型,但在此例中为空白 |
minerd | 是否为矿工进程(可能是一个自定义字段,表示操作的类型或来源) |
timestamp | 时间戳,指示操作发生的具体时间 |
op_text | 操作文本,实际执行的 SQL 操作语句,这里是一个 DELETE 操作 |
undo_text | 撤消文本,用于撤销操作的 SQL 语句,这里是一个 INSERT 操作 |
complete | 操作是否完成,这里为真(t 表示 true) |
relation | 关系名称,操作涉及的表或关系的名称 |
start_lsn | 开始的日志序列号(LSN),用于事务日志中的标识 |
commit_lsn | 提交的日志序列号(LSN),指示事务的提交点 |