全量备份和增量备份
时间线概念
时间线可以理解为版本或者分支
有了增量备份,已经可以实现按照时间点恢复,那为什么还要引入时间线?
比如在周三12点删错了一个表,但是周五才发现,这时候我们根据增量备份可以将数据库恢复到失误操作发生前的状态,比如周三11点,但是后来又根据实际情况需要恢复到周四早上8点。那么这是做不到的。因为在数据库不断运行中,会产生与旧的WAL文件重名的文件,这些文件进入归档目录时,会覆盖原来的旧日志,导致恢复数据库需要的 WAL文件丢失。为了避免这种情况,需要区分原始数据库历史生成的WAL文件和完成恢复之后继续运行产生的(重名的)新WAL文件。
为了解决这个问题,PostgreSQL引入了时间线的概念。每当归档文件恢复完成后,创建一个新的时间线用来区别新生成的WAL记录。
时间线ID号是WAL文件名组成之一,因此一个新的时间线不会覆盖由以前的时间线生成的WAL,每个时间线类似一个分支,在当前时间线的操作不会对其他时间线WAL造成影响,有了时间线,我们就可以恢复到之前的任何时间点。
环境
centos 7系统
postgresql 12
docker 20.10.6
试验步骤
配置postgresql.conf文件
- 归档命令中的路径要事先创建好
-
wal_level (枚举类型)
pg10版本中,待选的值为minimal、replica、logical。
minimal --不能通过基础备份和wal日志恢复数据库。
replica = 9.6版本以前的archive和hot_standby --该级别支持wal归档和复制。
logical --在replica级别的基础上添加了支持逻辑解码所需的信息 -
归档命令
%p = 恢复文件的路径 拼上 恢复文件的文件名 用“/”拼接
%f = 只有恢复文件的文件名
下面的归档命令实际上就是
cp pg_wal/000000010000000000000001 /home/test/archive/000000010000000000000001 && echo 000000010000000000000001 >> /home/test/archive/archive.list -
wal_keep_segments
pg_wal目录下所能保留的过去日志文件段的数目。每个段通常是 16 兆字节 -
/home/test/archive/
该目录必须为docker容器内的目录,如果想将其放到外部,需要使用docker挂载外面的目录.
#日志级别
wal_level = replica
#归档开关
archive_mode = on
#归档命令
archive_command = 'cp %p /home/test/archive/%f && echo %f >> /home/test/archive/archive.list'
#用于指定pg_wal目录中保存的过去的wal文件(wal 段)的最小数量
wal_keep_segments=1024
重启pg
docker-compose stop
查看归档目录
此后数据库的操作都会记录wal日志文件到/home/test/archive目录下
ls /home/test/archive/
000000010000000000000001 000000010000000000000002 000000010000000000000003 000000010000000000000004 archive.list
如果归档目录中没有内容,需要执行强制日志归档命令
select pg_switch_wal();
如果还是没有,查看数据库日志
如果报错cp:can not create XXX permission denied
给创建的归档目录授权777 然后再次重启 并查看 日志 看该报错是否消失
如果消失则再去查看归档目录 看是否有上面类似内容
如果没有 则执行强制归档命令select pg_switch_wal();
chmod 777 /home/test/archive
使用pg_basebackup进行基础备份
pg_basebackup的参数
- -F, p|t
指定输出格式:
p原样输出,即把主数据库中的各个数据文件,配置文件、目录结构都完全一样的写到备份目录;
t 把输出的备份文件打包到一个tar文件中。 - -z, --gzip
使用gzip压缩,仅能能与tar输出模式配合使用。 - -Z, --compress=0-9
指定压缩级别 - -x, --xlog (fetch mode)
备份时会把备份中产生的xlog文件也自动备份出来,这样才能在恢复数据库时,应用这些xlog文件把数据库推到一个一致点,然后真正打开这个备份的数据库,这个选项与 -X fetch是完全一样的。使用这个选项,需要设置“wal_keep_segments"参数,以保证在备份过程中,需要的WAL日志文件不会被覆盖。 - -P, --progress
在备份过程中实时打印备份进度 - -v, --verbose
详细模式,使用了-P后,还会打印出正在备份的具体文件的信息。 - -D
路径参数,指的依旧是容器内的路径,可以使用docker挂载
docker exec -u postgres -it test_db_1 pg_basebackup -h 127.0.0.1 -U odoo -p 5432 -Ft -Pv -Xf -z -Z5 -D /var/lib/postgresql/data/pgdata_bk
备份完成后,对应备份目录会出现基础备份 是一个压缩包
准备试验数据
在2022-03-10 16:40:00 创建表dog 并随意插入几条数据
等待适当时间,在16:43:00创建表cat 并随意插入几条数据
恢复时间点 2022-03-10 16:42:00 (创建两张表之间的时间点就行)
如果恢复后数据库中存在dog表,不存在cat表 则试验成功
模拟数据库故障
模拟数据库故障,停掉数据库
备份原来的data目录
cp -r _data data_bk
#删除原来data目录内容
rm -rf _data/*
#将备份的压缩包复制到data目录中并解压
cp data_bk/pgdata_bk/base.tar.gz _data/
tar -zxvf base.tar.gz
#删除备份
rm -rf base.tar.gz
修改postgresql.conf
设置归档命令和恢复时间点
设置恢复时间点的时候要注意时区问题
2>&1
2 > & 1 其实都是linux中的符号 包括0也是
0代表标准输入
1代表标准输出
2代表标准错误输出
代表重定向
整体含义:将标准错误输出重定向到标准输出
这个路径还是容器内的路径
restore_command = 'cp /home/test/archive/%f %p > /home/test/archive/recovery.log 2>&1 '
recovery_target_time = '2022-03-10 16:42:00'
添加空白文件recovery.signal文件
添加该文件 提醒postgresql要做recovery
touch recovery.signal
重启查看数据
查看数据是否符合预期
恢复后的数据库为只读模式 需要执行
select pg_wal_replay_resume()
使用到时间线的场景
还是时间线概念标题的例子,我们在周五恢复到周三,完成之后又要恢复到周四,显然没有时间线是不可行的,因为周三和周四在同一条时间线上,所以这个时候想恢复到周四,就要指定时间线。指定哪条时间线?指定周三那条时间线。每次恢复完成后,数据库会自动创建一条时间线,所以我们第二次恢复就要指定前面一条时间线。
查看当前时间线的命令
root@69a829dac2b6:/# pg_controldata |grep TimeLineID
Latest checkpoint's TimeLineID: 8
Latest checkpoint's PrevTimeLineID: 8
例如指定时间线参数
#指定时间线的时候 配的值为时间线的ID
recovery_target_timeline ='8'