作者:IT邦德
中国DBA联盟(ACDU)成员,10余年DBA工作经验,
Oracle、PostgreSQL ACE
CSDN博客专家及B站知名UP主,全网粉丝10万+
擅长主流Oracle、MySQL、PG、高斯及Greenplum备份恢复,
安装迁移,性能优化、故障应急处理
微信:jem_db
QQ交流群:587159446
公众号:IT邦德
文章目录
- 前言
 - 1.PITR说明
 - 2.开归档
 - 3.PITR恢复要点
 - 4.全量物理备份
 - 5.准备测试数据(源库)
 - 6.还原点恢复
 - 7.XID恢复
 - 8.恢复至lsn
 - 10.总结
 
前言
国产数据库使用的过程中,基于PITR的恢复非常的重要,这里给大家分享openGauss 基于PITR的恢复
1.PITR说明
当数据库崩溃或希望回退到数据库之前的某一状态时,opengauss的即时恢复功能( Point-In-Time Recovery,简称PITR ),可以支持恢复到备份归档数据之后的任意时间点。
 仅主节点可以进行PITR恢复,备机需要进行全量build达成与主机数据同步。
2.开归档
1.使用omm用户登录主库确认归档是否开启
查看当前归档日志相关参数,查看当前openGauss数据库管理系统的归档设置:
openGauss=# select name,setting from pg_settings 
where name like 'archive%' or name = 'wal_level';
       name       |   setting   
------------------+-------------
 archive_command  | (disabled)
 archive_dest     | 
 archive_interval | 1
 archive_mode     | off
 archive_timeout  | 0
 wal_level        | hot_standby
(6 rows)
说明:可以看出,数据库在非归档方式(参数archive_mode的值为off)。
vi $PGDATA/postgresql.conf
# 修改archive_mode的值需要重启动数据库
archive_mode=on
# 修改archive_command的值不需要重启动数据库,只需要reload
archive_command = 'cp %p /archivelog/%f'
# 修改archive_time:归档周期,900表示每900秒(15分钟)切换一次
archive_timeout = 900
用Linux用户omm,执行下面的命令,启动openGauss数据库:
gs_om -t restart
再次查看归档日志相关参数
执行下面的命令,查看当前openGauss数据库的归档设置:
[omm@centos79 ~]$ gsql -c 
"select name,setting from pg_settings where name like 'archive%' or name = 'wal_level'"
       name       |       setting        
------------------+----------------------
 archive_command  | cp %p /archivelog/%f
 archive_dest     | 
 archive_interval | 1
 archive_mode     | on
 archive_timeout  | 900
 wal_level        | hot_standby
(6 rows)
 
3.PITR恢复要点
PITR恢复流程:
1.将物理备份的文件替换目标数据库目录。
2.删除数据库目录下pg_xlog/中的所有文件。
3.将归档的WAL日志文件复制到pg_xlog文件中
4.在数据库目录下创建恢复命令文件recovery.conf,指定数据库恢复的程度。
5.启动数据库。
6.连接数据库,查看是否恢复到希望预期的状态。
7.若已经恢复到预期状态,通过pg_xlog_replay_resume()指令使主节点对外提供服务。
####  归档恢复配置  ####
## 该SHELL命令获取已归档的WAL文件。
restore_command = 'cp /gauss/bak/archive/%f %p'   
## 清理备库WAL归档日志的shell命令,每次重启时会执行
archive_cleanup_command = 'pg_archivecleanup /gauss/bak/archive %r' 
#### 恢复目标设置(四选一) ####
## 还原到一个使用pg_create_restore_point()创建的还原点
recovery_target_name = 'restore_point_1'  
## 还原到一个指定时间戳    
recovery_target_time = '2020-01-01 12:00:00'  
 ## 还原到一个事务ID
recovery_target_xid = '3000'       
 ## 还原到日志的指定LSN点          
recovery_target_lsn = '0/0FFFFFF'  
 ## 声明是否在指定恢复目标之后停止(true) 或 之前停止(false),不支持recovery_target_name 配置          
recovery_target_inclusive = true             
## 注意:如果不配置任何恢复目标 或 配置目标不存在,则默认恢复到最新的WAL日志点。
 
4.全量物理备份
#使用gs_basebackup全量备份
创建备份文件存储目录,gs_basebackup备份
数据库需要处于开启状态
[omm@centos79 ~]$ mkdir -p /home/omm/gs_bak
[omm@centos79 ~]$ gs_basebackup -D /home/omm/gs_bak -p 15400
INFO:  The starting position of the xlog copy of the full build is: 0/E000028. The slot minimum LSN is: 0/0. The disaster slot minimum LSN is: 0/0. The logical slot minimum LSN is: 0/0.
[2024-09-19 05:49:45]:begin build tablespace list
[2024-09-19 05:49:45]:finish build tablespace list
[2024-09-19 05:49:45]:begin get xlog by xlogstream
[2024-09-19 05:49:45]: check identify system success                                                
[2024-09-19 05:49:45]: send START_REPLICATION 0/E000000 success                                     
[2024-09-19 05:49:45]: keepalive message is received                                                
[2024-09-19 05:49:45]: keepalive message is received                                                
[2024-09-19 05:49:50]:gs_basebackup: base backup successfully
 
5.准备测试数据(源库)
1)记录操作的起始位置
--创建测试数据
openGauss=# \c testdb
testdb=# \dt
                          List of relations
 Schema |  Name   | Type  | Owner |             Storage              
--------+---------+-------+-------+----------------------------------
 public | test    | table | omm   | {orientation=row,compression=no}
 public | testbak | table | omm   | {orientation=row,compression=no}
(2 rows)
-- 创建一个还原点restore_point_1
testdb=# select pg_create_restore_point('restore_point_1');
 pg_create_restore_point 
-------------------------
0/F00B638
(1 row)
2)创建测试数据t1表(源库),切日志
drop table t1;
create table t1(name varchar(50));
insert into t1 values('This is restore_point_1');
testdb=# select pg_switch_xlog();
 pg_switch_xlog 
----------------
 0/F016398
(1 row)
testdb=# select pg_switch_xlog();
 pg_switch_xlog 
----------------
 0/10000A68
(1 row)
3)记录第一次数据插入后的数据库位置
testdb=# \x
Expanded display is on.
testdb=# select * from pg_get_variable_info();
-[ RECORD 1 ]------------+-----------
node_name                | dn_6001
next_oid                 | 16417
next_xid                 | 45588
oldest_xid               | 12666
xid_vac_limit            | 4000012666
oldest_xid_db            | 15649
last_extend_csn_logpage  | 63
start_extend_csn_logpage | 0
next_commit_seqno        | 3298
latest_completed_xid     | 45587
startup_max_xid          | 45154
-- 查看最近提交的XID(latestCompletedXid-->45587 || nextXid-->45588)
4)创建测试数据t2表(源库)
-- 创建表t2并插入数据
create table t2(name varchar(50));
insert into t2 values('This is insert into t2');
testdb=# select pg_current_xlog_location();
 pg_current_xlog_location 
--------------------------
 0/1100BE28
(1 row)
testdb=# select pg_switch_xlog();
 pg_switch_xlog 
----------------
 0/1100D060
(1 row)
testdb=# select pg_switch_xlog();
 pg_switch_xlog 
----------------
 0/12001368
(1 row)
5)记录第二次数据插入后的数据库位置
-- 查询当前LSN 数据库t1、t2
testdb=# select pg_current_xlog_location();
 pg_current_xlog_location 
--------------------------
 0/13002E60
(1 row)
 
6.还原点恢复
配置recovery.conf文件(基于还原点restore_point_1恢复)
#创建recovery.conf文件
cd /home/omm/data/db1/
cat> recovery.conf<<EOF
restore_command = 'cp /archivelog/%f %p'
archive_cleanup_command = 'pg_archivecleanup /archivelog  %r'
recovery_target_name = 'restore_point_1'   ## 恢复到指定的还原点restore_point_1,此时还没有创建表t1和t2 
recovery_target_inclusive = true
EOF
#由于在本机操作,关闭源数据库,避免port冲突
$ gs_om -t stop
#启动恢复目标数据库并查看数据,数据目录: /home/omm/data/db1
$ gs_ctl start -D  /home/omm/data/db1
-- 检查当前数据库是否处于恢复状态 
gsql -r -d testdb
openGauss=# select pg_is_in_recovery();
 pg_is_in_recovery 
-------------------
 t
(1 row)
openGauss=# select pg_current_xlog_location();
ERROR:  recovery is in progress
HINT:  WAL control functions cannot be executed during recovery.
CONTEXT:  referenced column: pg_current_xlog_location
openGauss=# drop table t1;
ERROR:  cannot execute DROP TABLE in a read-only transaction
恢复说明:
表t1和t2都不存在,且处于恢复状态数据库无法使用函数查看LSN位置,该数据库只读
#查看日志中的恢复情况
cd /openGauss/log/omm/omm/pg_log/dn_6001
grep -C 3 "restore_point_1"  /openGauss/log/omm/omm/pg_log/dn_6001/postgresql-2024-09-19_060448.log
 

7.XID恢复
-- 修改recovery_target,继续往前恢复
cd /home/omm/data/db1/
mv recovery.done recovery.conf
vi recovery.conf
--------------------------
# 根据前面的信息得知,xid=19251这个事务完毕时,仅有t1表,没有t2表
# 我们这一阶段仅恢复t1表即可
# 修改:
recovery_target_xid = '45587'  
--------------------------
-- 重启恢复测试数据
gs_ctl restart -D /home/omm/data/db1/
-- 检查当前数据库是否处于恢复状态 
gsql -r -d testdb
openGauss=# select pg_is_in_recovery();
 pg_is_in_recovery 
-------------------
 t
(1 row)
testdb=# \dt
                                    List of relations
 Schema |  Name   | Type  | Owner |                       Storage                        
--------+---------+-------+-------+------------------------------------------------------
 public | t1      | table | omm   | {orientation=row,compression=no,storage_type=USTORE}
 public | test    | table | omm   | {orientation=row,compression=no}
 public | testbak | table | omm   | {orientation=row,compression=no}
(3 rows)
testdb=# select * from t1;
          name           
-------------------------
 This is restore_point_1
(1 row)
恢复说明:此时数据仅恢复了表t1,并未恢复表t2,实验结果满足预期目标                      ^
-- 从日志中我们也可以看到,数据库恢复至xid=45587后
#查看日志中的恢复情况
cd /openGauss/log/omm/omm/pg_log/dn_6001
grep -C 3 "45587"  /openGauss/log/omm/omm/pg_log/dn_6001/postgresql-2024-09-19_061518.log
 

8.恢复至lsn
-- 修改recovery_target,继续往前恢复
cd /home/omm/data/db1/
mv recovery.done recovery.conf
vi recovery.conf
# 根据前面的信息得知,lsn='0/13002E60'这个LSN位置时,t1表和t2表已经创建完毕
# 修改:
recovery_target_lsn = '0/13002E60'
-- 重启恢复测试数据
gs_ctl restart -D /home/omm/data/db1/
-- 检查当前数据库是否处于恢复状态 
gsql -r -d testdb
openGauss=# select pg_is_in_recovery();
 pg_is_in_recovery 
-------------------
 t
(1 row)
testdb=# \dt
                                    List of relations
 Schema |  Name   | Type  | Owner |                       Storage                        
--------+---------+-------+-------+------------------------------------------------------
 public | t1      | table | omm   | {orientation=row,compression=no,storage_type=USTORE}
 public | t2      | table | omm   | {orientation=row,compression=no,storage_type=USTORE}
 public | test    | table | omm   | {orientation=row,compression=no}
 public | testbak | table | omm   | {orientation=row,compression=no}
(4 rows)
testdb=# select * from t1;
          name           
-------------------------
 This is restore_point_1
(1 row)
testdb=# select * from t2;
          name          
------------------------
 This is insert into t2
(1 row)
-- 从日志中我们也可以看到,数据库恢复至LSN=0/13002E60后,
检测到Double-write日志后续内容为空(Empty),则认为数据库已恢复至最新状态,此时恢复任务结束(Finish)
#查看日志中的恢复情况
cd /openGauss/log/omm/omm/pg_log/dn_6001
grep -A 5 "0/13002E60"  /openGauss/log/omm/omm/pg_log/dn_6001/postgresql-2024-09-19_062157.log
 

9.结束PITR
当未将数据库恢复至最新时刻状态时,此时需要手动结束PITR恢复任务。
-- 查询数据库恢复状态
testdb=# select pg_is_in_recovery();
 pg_is_in_recovery 
-------------------
 t
(1 row)
 
-- 结束恢复,使机器对外提供读写服务
testdb=# select pg_xlog_replay_resume();
 pg_xlog_replay_resume
-----------------------
-- 查询数据库恢复状态(已结束)
testdb=# select pg_is_in_recovery();
 pg_is_in_recovery 
-------------------
 f
(1 row)
--可以看到目前数据库可以读写了
testdb=# drop table testbak;
DROP TABLE
 
10.总结
%f即归档检索中的文件名,%p即复制目的地的路径名,%r最新可用重启点的文件名
 如果多个备机从相同的归档路径恢复时,需要确保该路径存在所有备机恢复所需要的WAL文件。
 整个恢复的过程为了方式端口被占用,请关闭原库



















