连续归档和时间点恢复(PITR)
连续归档设置
所谓WAL日志归档,其实就是把在线的WAL日志备份出来。
要启用WAL归档,需设置wal_level配置参数为replica或更高,设置archive_mode为on,并且使用archive_command配置参数指定一个shell命令。
在pg中配置归档的方法就是配置参数archive_command,参数的配置值是一个Unix命令。此命令把WAL日志文档拷贝到其他的地方。例:
archive_command = ‘cp %p /backup/pgwal/%f’;
//cp 命令。实际执行时,pg会把%p 替换成实际的在线WAL日志文件的全路径名,并把%f替换成不包括路径的WAL日志名。
最后被执行的时候是下面这样:
cp pg_wal/00000001000000A900000065 /backup/pgwal/00000001000000A900000065
对每一个将要被归档的新文件都会生成一个类似的命令。
我们也可以归档到远程计算机:
archive_command ='scp %p postgres@192.168.100.100:/backup/pgwal/%f';
什么情况下会触发归档?
建立归档后,什么情况下会触发归档?
方法一:手动切换 WAL 日志
PostgreSQL 提供 pg_switch_xlog() 函数可以手工切换 WAL 日志,如下:
--手动归档
Type "help" for help.
postgres=# select pg_switch_xlog();
pg_switch_xlog
----------------
0/87000000
(1 row)
备注:执行 pg_switch_xlog() 后,WAL 会切换到新的日志,这时会将老的 WAL日志归档
方法二:WAL 日志写满后触发归档
WAL 日志被写满后会触发归档,文档在说明配置参数 archive_command 时的第一句说就说明了这点, WAL 日志文件默认为 16MB,这个值可以在编译 PostgreSQL 时通过参数 “–with-wal-segsize” 更改,编译后不能修改。
方法三:设置 archive_timeout
另外可以设置archive 超时参数 archive_timeout ,假如设置 archive_timeout=60 ,那么每 60 s ,
会触发一次 WAL 日志切换,同时触发日志归档,这里有个隐含的假设: 当前 WAL 日志中仍有未归档的 WAL 日志内容.
注:尽量不要把archive_timeout设置的很小,如果设置的很小,他会膨胀你的归档存储,因为,你强制归档的日志,即使没有写满,也会是默认的16M(假设wal日志写满的大小为16M)
PIRT恢复
实现目标: 恢复到指定时间点
实现步骤: 基于数据库做基础备份
插入新数据
删除表中部分数据
基于备份做指定时间点的恢复
验证数据是否恢复
一.前期准备
- 开启WAL归档
vim postgresql.conf
wal_level='replica' #wal_level至少设置为replica
archive_mode='on'
archive_command='cp %p /backup/pgarch'
#注意/backup/pgarch目录的属主属组都要为postgres(chown -R postgres:postgres /backup/pgarch )
- 备份
pg_basebackup -Ft -Pv -Xf -z -Z5 -p5432 -D /pdback
- 初始化数据
create table test01(id int primary key,name varchar(20));
insert into test01 values(1,'a'),(2,'b'),(3,'c');
- 备份完之后做一次WAL切换,保证最新的WAL日志归档到归档目录
select pg_switch_wal();
二.恢复到某一时间点
模拟情景
- test01表目前有四条数据
select * from test01;
id | name
----+------
1 | a
2 | b
3 | c
4 | d
- 误操作将数据删除
delete from test01;
select * from test01;
id | name
----+------
- 数据恢复
#先查看一下当前的时间戳
select current_timestamp;
current_timestamp
-------------------------------
2018-09-10 09:54:55.794813+08
select pg_switch_wal();
pg_switch_wal
---------------
2/DA0003E0
#删除操作大概是3分钟之前的操作,那么将这个时间戳往前推3分钟,切换一下wal日志,确保最新的wal日志同步到归档目录
#思路是利用最新的备份+wal日志恢复数据
示例
- 将之前的数据目录备份一下
pg_ctl stop
mv /pgdata /pgdata.bak
- 将最新的备份恢复到数据目录
mkdir /pgdata
vim recovery.done
restore_command='cp /backup/pgarch/%f %p'
recovery_target_time='2018-09-10 09:51:55.794813+08'
recovery_target_timeline='latest'
mv ./recovery.done ./recovery.conf
chown -R postgres:postgres /pgdata
chmod 700 /pgdata
select * from test01;
id | name
----+------
1 | a
2 | b
3 | c
4 | d
#可以看到数据已恢复
- 解除暂停状态
select pg_wal_replay_resume();
三.恢复到指定还原点
情景模拟
select * from test01;
id | name
----+------
1 | a
2 | b
3 | c
4 | d
select pg_create_restore_point('rp1');
pg_create_restore_point
-------------------------
2/D90003B0
#创建一个还原点
drop table test01;
select pg_switch_wal();
pg_switch_wal
---------------
2/DA005700
恢复
思路:最新的备份+wal日志
- 将备份恢复,配置recovery.conf文件
vim recovery.conf
restore_command='cp /backup/pgarch/%f %p'
recovery_target_name='rp1'
recovery_target_timeline='latest'
- 启动并进入数据库,查看数据是否被恢复
select * from test01 ;
id | name
----+------
1 | a
2 | b
3 | c
4 | d
#可以看到数据已经被恢复了
#当前数据库状态为pause状态(recovery_target_action),我们可以判断当前的数据是否满足我们的预期值,如果不满足,那么可以继续向后推,直到达到我们的预期值
- 解除暂停状态
select pg_wal_replay_resume();
四.恢复到指定事务
情景模拟
select * from test01 ;
id | name
----+------
1 | a
2 | b
3 | c
4 | d
begin;
select txid_current();
txid_current
--------------
342261
drop table test01 ;
end;
select pg_switch_wal();
假设要恢复表test01的数据,示例
- 将最新的备份恢复后,配置recovery.conf文件
vim recovery.conf
restore_command='cp /backup/pgarch/%f %p'
recovery_target_xid='342261'
recovery_target_inclusive = false
recovery_target_timeline='latest'
- 启动并进入数据库,检查test01数据是否恢复
select * from test01 ;
id | name
----+------
1 | a
2 | b
3 | c
4 | d
#恢复成功
- 关闭数据库pause状态
select pg_wal_replay_resume()