所谓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 [email protected]:/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)
实现目标: 恢复到指定时间点
实现步骤: 基于数据库做基础备份
插入新数据
删除表中部分数据
基于备份做指定时间点的恢复
验证数据是否恢复
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');
select pg_switch_wal();
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日志
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();
vim recovery.conf
restore_command='cp /backup/pgarch/%f %p'
recovery_target_xid='342261'
recovery_target_inclusive = false
recovery_target_timeline='latest'
select * from test01 ;
id | name
----+------
1 | a
2 | b
3 | c
4 | d
#恢复成功
select pg_wal_replay_resume()