在生产环境中的备份恢复以及流复制搭建的基础数据备份,一般是使用pg_basebackup实现。
1、原理简介
pg_basebackup--获得一个PostgreSQL集簇的一个基础备份。
pg_basebackup是集合API函数pg_start_backup和pg_stop_backup,在9.1版本之前的物理备份可以通过pg_start_backup和pg_stop_backup函数来进行实现备份,对于pg_basebackup来说步骤较多,注意的事项也比较多(比如复制槽、表空间等问题)。
备份通过一个使用复制协议与PostgreSQL连接操作。该连接必须由一个具有REPLICATION权限或者具有超级用户权限的用户ID建立,并且pg_hba.conf必须允许该复制连接。该服务器还必须被配置,使max_wal_senders设置得足够高以提供至少一个wal sender用于备份以及一个用于WAL流传输(如果使用流)。
实现步骤:
1、执行pg_start_backup函数:该函数执行checkpoint,将checkpoint信息写入数据目录下的 backup_label文件,该文件很重要,否则启动实例的时候会提示找不到检查点。同时在归档目录下会对正在使用的归档日志进行标记。
2、拷贝数据目录到指定位置
3、执行pg_stop_backup 函数:该命令删除backup_label 文件,写WAL_BACKUP_END 日志,并在pg_wal目录中写入backup该文件记录了热备开始和结束的LSN信息。
backup文件格式为:热备开始的日志文件名.开始 lsn 的块内偏移.backup
pg_basebackup用于对正在运行的PostgreSQL数据库集群进行基本备份。备份是在不影响数据库的其他客户端的情况下进行的,并且可以用于时间点恢复和作为日志传送或流复制备用服务器的起点 。
pg_basebackup不仅可以从主服务器也可以从备用服务器进行基本备份。要从备用数据库进行备份,需设置备用数据库以便它可以接受复制连接(即 set max_wal_senders和hot_standby,并对其进行pg_hba.conf适当配置)。您还需要在主节点上启用full_page_writes。
2、参数说明
pg_basebackup [OPTION] ...
控制输出的选项:
-D, --pgdata=DIRECTORY 接收基本备份的目标目录
-F, --format=p|t 输出格式(plain(默认),tar)
-r, --max-rate=RATE 传输数据目录的最大传输速率(以 kB/s 为单位,或使用后缀“k”或“M”)
-R, --write-recovery-conf 用于复制的写入配置
-T, --tablespace-mapping=OLDDIR=NEWDIR 将OLDDIR中的表空间重定位到NEWDIR
--waldir=WALDIR 预写日志目录的位置
-X, --wal-method=none|fetch|stream 包含指定方法所需的WAL文件
-z, --gzip 压缩 tar 输出
-Z, --compress=0-9 使用给定的压缩级别压缩 tar 输出
常规选项:
-c, --checkpoint=fast|spread 设置快速或扩展检查点
-C, --create-slot 创建复制槽
-l, --label=LABEL 设置备份标签
-n, --no-clean 出错后不清理
-N, --no-sync 不等待更改安全写入磁盘
-P, --progress 显示进度信息
-S, --slot=SLOTNAME 要使用的复制槽
-v, --verbose 输出详细信息
-V, --version 输出版本信息,然后退出
--no-slot 防止创建临时复制槽
--no-verify-checksums 不验证校验和
-?, --help 显示此帮助,然后退出
连接选项:
-d, --dbname=CONNSTR 连接字符串
-h, --host=HOSTNAME 数据库服务器主机或套接字目录
-p, --port=PORT 数据库服务器端口号
-s, --status-interval=状态包发送到服务器的间隔时间(以秒为单位)
-U, --username=NAME 以指定的数据库用户连接
-w, --no-password 从不提示输入密码
-W, --password 强制密码提示(应该自动
3、恢复目标
默认情况下,恢复将恢复到WAL日志的末尾即,备份那一刻的日志。即recovery_target默认为immediate。
recovery_target='immediate' 指定恢复应该在达到一个一致状态后尽快结束,即尽早结束。在从一个在线备份中恢复时,这意味着备份结束的那个点。
recovery_target_name=string 指定恢复将继续进行到已命名的恢复点(pg_create_restore_point()创建)。
recovery_target_time=timestamp 这个参数指定恢复将继续执行到指定时间戳。精确的停止点也受到recovery_target_inclusive的影响。
recovery_target_xid=string 指定恢复将继续执行到指定事务ID。
recovery_target_timeline=string 指定恢复到一个特定的时间线中。默认值是沿着基础备份建立时的当前时间线恢复。将这个参数设置为latest会恢复到该归档中能找到的最新的时间线,这在一个后备服务器中有用。
recovery_target_inclusive=boolean 指定我们是否在指定的恢复目标之后停止(true),或者在恢复目标之前停止(false)。
recovery_target_action (enum) (boolean) 指定当到达恢复目标时服务器应该采取什么动作。默认值是pause,这意味着将暂停恢复。promote意味着将结束恢复进程并且服务器开始接受连接。 shutdown将在到达恢复目标后停止服务器。
基于时间点注意事项:
1、归档日志完整
2、指定从归档目录拷贝WAL文件restore_command = 'cp /data/pgarchive/%f %p'
3、设置recovery_target_time 或 recovery_target_lsn 或 recovery_target_xid等恢复目标位置
4、创建touch $PGDATA/recovery.signal
Startup进程作用
崩溃恢复的核心进程是startup,核心函数是StartupXLOG,它在数据库启动时就会被调用,读取配置信息,应用WAL日志。
通过读取不同参数,startup进程可以完成3大功能:崩溃恢复、从库日志应用、PITR(基于时间点的恢复)。
判断方式:
在数据库目录下可以创建standby.signal或者recovery.signal文件,Startup进程会检查这两个文件是否存在。
1、若都不存在,执行普通的崩溃恢复,应用到最新日志。
2、若standby.signal文件存在,则当前数据库是从库,持续进行日志应用。
3、若recovery.signal文件存在,则进行PITR操作,根据recovery_target应用日志。
注:从12开始已经不再支持recovery.conf文件,如果检测到会报错。
4、备份进度
从版本14开始,备份进行可以通过下面这个视图查询:pg_stat_progress_basebackup。
5、示例参考
PGDATA=/data/pgdata
前提条件:
1、创建归档和备份目录
mkdir /data/pgarchive /data/pgbackup
chown -R postgres.postgres /data/pgarchive /data/pgbackup
2、开启归档模式
vi postgresql.conf
wal_level = 'replica'
archive_mode = 'on'
archive_command = 'cp %p /data/pgdata/pgarchive/%f'
3、创建复制权限用户
创建replication权限的角色, 或者超级用户的角色。
create role repuser nosuperuser replication login connection limit 5 encrypted password 'repuser';
示例1:恢复到最新时间线
全量备份和恢复到最新时间线。
#创建测试数据表
create table t1(id int not null primary key, name varchar(30));
insert into t1(id, name) values(1, '张三'), (2, '李四');
#执行全量备份
pg_basebackup -h 127.0.0.1 -p 5432 -U postgres -D /data/pgbackup
#模拟数据库故障
drop table t1;
select pg_switch_wal();
checkpoint;
#启动备份实例,进行数据恢复
pg_ctl stop -D /data/pgdata
cd /data/pgbackup
vi postgresql.conf
recovery_target_timeline = 'latest'
recovery_target_action = 'shutdown'
restore_command = 'cp /data/pgarchive/%f %p'
#创建恢复标签文件
touch recovery.signal #告诉PostgreSQL进入正常的归档模式
#touch standby.signal #告诉PostgreSQL进入standby模式
#启动恢复库实例
pg_ctl start -D /data/pgbackup
#关闭读模式
select pg_wal_replay_resume();
#写入数据测试
insert into t1(id, name) values(3,'王五');
select * from t1;
示例2:恢复到指定时间点
全量备份结合时间点进行恢复。
#关闭备份实例,启动原始实例
pg_ctl stop -D /data/pgbackup
rm -rf /data/pgbackup/*
pg_ctl start -D /data/pgdata
#执行全量备份
pg_basebackup -h 127.0.0.1 -p 5432 -U postgres -D /data/pgbackup
#创建测试数据
create table t1(id int not null primary key, demo varchar(60));
insert into t1(id, demo) values(1, '全量备份'), (2, '结合时间点进行恢复');
#有变化数据,执行增量备份
pg_receivewal -h 127.0.0.1 -p 5432 -D /data/pgbackup
#模拟数据丢失
drop table t1;
select current_timestamp;
select pg_switch_wal();
checkpoint;
#启动备份实例,进行数据恢复
pg_ctl stop -D /data/pgdata
cd /data/pgbackup
vi postgresql.conf
recovery_target_time = '2023-10-10 19:38:20.687536+08'
recovery_target_action = 'shutdown'
restore_command = 'cp /data/pgarchive/%f %p'
#创建恢复标签文件
touch recovery.signal #告诉PostgreSQL进入正常的归档模式
#touch standby.signal #告诉PostgreSQL进入standby模式模式
#启动恢复库实例
pg_ctl start -D /data/pgbackup
#关闭读模式
select pg_wal_replay_resume();
示例3:恢复到指定恢复点
全量备份结合还原点进行恢复。
#关闭备份实例,启动原始实例
pg_ctl stop -D /data/pgbackup
rm -rf /data/pgbackup/*
pg_ctl start -D /data/pgdata
#执行全量备份
pg_basebackup -h 127.0.0.1 -p 5432 -U postgres -D /data/pgbackup
#创建测试数据
create table t1(id int not null primary key, demo varchar(60));
insert into t1(id, demo) values(1, '全量备份'), (2, '结合还原点进行恢复');
#创建还原点
select pg_create_restore_point('huanyuan');
#模拟数据丢失
drop table t1;
select pg_switch_wal();
checkpoint;
#有变化数据,执行增量备份
pg_receivewal -h 127.0.0.1 -p 5432 -D /data/pgbackup
#启动备份实例,进行数据恢复
pg_ctl stop -D /data/pgdata
cd /data/pgbackup
vi postgresql.conf
recovery_target_name = 'huanyuan'
recovery_target_action = 'shutdown'
restore_command = 'cp /data/pgarchive/%f %p'
#创建恢复标签文件
touch recovery.signal #告诉PostgreSQL进入正常的归档模式
#touch standby.signal #告诉PostgreSQL进入standby模式
#启动恢复库实例
pg_ctl start -D /data/pgbackup
#关闭读模式
select pg_wal_replay_resume();
示例4:恢复到指定XID点
全量备份结合指定事务进行恢复。
#关闭备份实例,启动原始实例
pg_ctl stop -D /data/pgbackup
rm -rf /data/pgbackup/*
pg_ctl start -D /data/pgdata
#执行全量备份
pg_basebackup -h 127.0.0.1 -p 5432 -U postgres -D /data/pgbackup
#创建测试数据
create table t1(id int not null primary key, demo varchar(60));
insert into t1(id, demo) values(1, '全量备份'), (2, '结合指定事务进行恢复');
#查询当前事务号
select pg_current_xact_id(); 或者 select txid_current();
#有变化数据,执行增量备份
pg_receivewal -h 127.0.0.1 -p 5432 -D /data/pgbackup
#模拟数据丢失
drop table t1;
select pg_switch_wal();
checkpoint;
#启动备份实例,进行数据恢复
pg_ctl stop -D /data/pgdata
cd /data/pgbackup
vi postgresql.conf
recovery_target_xid = '678'
recovery_target_action = 'shutdown'
restore_command = 'cp /data/pgarchive/%f %p'
#创建恢复标签文件
touch recovery.signal #告诉PostgreSQL进入正常的归档模式
#touch standby.signal #告诉PostgreSQL进入standby模式模式
#启动恢复库实例
pg_ctl start -D /data/pgbackup
#关闭读模式
select pg_wal_replay_resume();
示例5:恢复到指定LSN点
全量备份结合LSN号码进行恢复。
#关闭备份实例,启动原始实例
pg_ctl stop -D /data/pgbackup
rm -rf /data/pgbackup/*
pg_ctl start -D /data/pgdata
#执行全量备份
pg_basebackup -h 127.0.0.1 -p 5432 -U postgres -D /data/pgbackup
#创建测试数据
create table t1(id int not null primary key, demo varchar(60));
insert into t1(id, demo) values(1, '全量备份'), (2, '结合指定LSN号进行恢复');
#查询当前LSN号
select pg_current_wal_lsn();
#有变化数据,执行增量备份
pg_receivewal -h 127.0.0.1 -p 5432 -D /data/pgbackup
#模拟数据丢失
drop table t1;
select pg_switch_wal();
checkpoint;
#启动备份实例,进行数据恢复
pg_ctl stop -D /data/pgdata
cd /data/pgbackup
vi postgresql.conf
recovery_target_lsn = '0/4011BF8'
recovery_target_action = 'shutdown'
restore_command = 'cp /data/pgarchive/%f %p'
#创建恢复标签文件
touch recovery.signal #告诉PostgreSQL进入正常的归档模式
#touch standby.signal #告诉PostgreSQL进入standby模式模式
#启动恢复库实例
pg_ctl start -D /data/pgbackup
#关闭读模式
select pg_wal_replay_resume();




