1.pg_basebackup备份工具
该备份工具自动执行 pg_start_backup()和 pg_stop_backup()函数,而且备份速度和数据都比手动的备份快。
代码语言:javascript复制1、 数据库处于归档模式
2、 备份:
a) 产生压缩的 tar 包,-Ft 参数指定:
pg_basebackup -D bk1 -Ft -z -P 此备份花的时间比较长,但是节省空间。
b) 产生跟源文件一样的格式,即原样格式,-Fp 参数指定:
pg_basebackup -D bk2 -Fp -P 此备份方式很快,但是不节省空间。
3、 恢复:
a) 关闭数据库或者 kill 服务器主进程模拟主机断电
pg_ctl stop
b) 删除 data 目录下所有的文件,(如果是删除这个 data 目录,则下一次创建该目录时要求该目录的权限是 750,否则启动数据库时会报错):
rm –rf $PGDATA/*
c) 使用 tar 包进行恢复:
tar -zvxf bk1/base.tar.gz -C /usr/local/pg12.2/data
tar -zvxf bk1/pw_wal.tar.gz -C /usr/local/pg12.2/data/pg_wal
d)或者使用原样文件备份进行恢复:
cp –rf bk2/* $PGDATA
e)在 postgres.conf 文件中添加如下 2 行:
restore_command = 'cp /home/postgres/arch/%f %p' recovery_target_timeline = 'latest'
f) 在$PGDATA 目录下 touch 一个空文件,告诉 pg 需要做 recovery: touch recovery.signal
g) 启动数据库: pg_ctl start
h) 登录数据库,执行函数(否则 pg 数据库处于只读状态):
select pg_wal_replay_resume();
g)验证数据的完整性:
testdb=# select count(*) from t1;
count 524288
注意: 把数据库文件转储出来后,在启动数据库前 postgresql.conf 一定要添加恢复参数,否则只恢复到备份的时间点。 经过测试,第一次恢复后,数据库能够恢复到最新状态,t1 表的数据能够恢复到归档的最后位置。对数据库进行操作,切换几个日志后,再用之前的备份对数据库进行恢复,结果能够恢复到最新的状态,能够自动应用归档,此恢复方式比 mysql 要智能。 如果当前的日志丢失,pg 实际上做的是不完全恢复,但是恢复的时候没有提示,而且不需要显式进行 recovery,在启动数据库的时候自动运行,类似 oracle 的实例恢复。
2. Point-in-Time Recovery
Point-in-Time Recovery (PITR)(基于时间点的恢复)
代码语言:javascript复制默认情况下,恢复将会一直恢复到 WAL 日志的末尾。 在 recovery_target 、recovery_target_lsn、recovery_target_name、recovery_target_time 和 recovery_target_xid 中, 最多只能使用一个,如果在配置文件中使用了多个,将使用最后一个。
recovery_target = 'immediate' :这个参数指定恢复应该在达到一个一致状态后尽快结束, 即尽早结束。在从一个在线备份中恢复时,这意味着备份结束的那个点。
recovery_target_name (string) :指定(pg_create_restore_point()所创建)的已命名的恢复点,进行恢复。
recovery_target_time (timestamp) :这个参数指定按时间戳恢复。
recovery_target_xid (string) :这个参数指定按事务 ID 进行恢复。
recovery_target_lsn (pg_lsn) :这个参数指定按继续进行的预写日志位置的 LSN 进行恢复。
recovery_target_inclusive (boolean):指定我们是否仅在指定的恢复目标之后停止(true),
或者仅在恢复目标之前停止(false)。 适用于 recovery_target_lsn、recovery_target_time 或者 recovery_target_xid 被指定的情况。 这个设置分别控制事务是否有准确的目标 WAL 位置(LAN)、提交时间或事务 ID 将被包括在该恢复中。 默认值为 true。
recovery_target_timeline (string) :指定恢复到一个特定的时间线中。默认值是沿着基础备份建立时的当前时间线恢复。将这个参数设置为 latest 会恢复到该归档中能找到的最新的时间线。
recovery_target_action (enum) :指定在达到恢复目标时服务器应该立刻采取的动作,包括 pause(暂停)、promote(接受连接)、shutdown(停止服务器),其中 pause 为默认动作。
2.1基于命名还原点恢复
数据库的 PITR 是一般数据库都必须满足的技术; 其原理是依据之前的物理备份文件加上 wal 的预写日志模式备份做的恢复; 该技术支持 8.*及以上版本。 recovery.conf 文件还原点控制参数 --12.0 版本以下的 postgresql.conf 文件还原点控制参数 12.0 版本以上
代码语言:javascript复制1) 命名的还原点
recovery_target_name = 'first-pt'
指 pg_create_restore_point(text)创建的还原点,如果数据库中有多个重复命名的还原点, 遇到第一个则停止。因 为 它 不 需 要 abort 或 chepoint 判 断 结 束 点 , 不 需 要 判断 参 数 recovery_target_inclusive 的。
2) 目标时间还原点
recovery_target_time = '2020-02-27 06:53:42'
指 WAL 中 记 录 recordXtime(xl_xact_commit_compact->xact_time); 如果在同一个时间点有多个事务回滚或提交:
其值为 false 则恢复到这个时间点第一个回滚或提交的事务(含) 其值为 true 则恢复到这个时间点最后一个回滚或提交的事务(含) 如果时间点上刚好只有 1 个事务回滚或提交:那么其值为 true 和 false 一样, 恢复将处理到这个事务包含的 wal 信息(含) 如果时间点没有匹配的事务提交或回滚信息:那么其值 true 和 false 一样, 恢复将处理到这个时间后的下一个事务回滚或提交的wal 信息
3) ID 事务还原点
recovery_target_xid, 指 WalRecord->xl_xid, 可以配合 recovery_target_inclusive 使用, 但是 recovery_target_inclusive 只影响日志的输出, 并不影响恢复进程截至点的选择,截止于这个 xid 的 wal 位置. 也就是说无论如何都包含了这个事务的 wal 信息的recovery.
这里需要特别注意 xid 的信息体现在结束时, 而不是分配 xid 时. 所以恢复到xid=100 提交回滚点, 可能 xid=102 已经先提交了. 那么包含 xid=102 的 wal 信息会被recovery.
结论:PITR 技术对于 7*24 小时支撑是至关重要的,但是如果数据库非常小,增大pg_dump 备份的频率可能更方便,但对于大数据库就需要了。
2.2基于 recovery_target_name
代码语言:javascript复制先以 pg_basebackup 的方法完成一个基础备份,参考指令如下:
mkdir /home/postgres/bk/`date %F`
pg_basebackup -F t –D /home/postgres/bk/`date %F`
如果要压缩,则加一个参数-z 即可:
pg_basebackup -F t -z -D /home/postgres/bk/`date %F`
代码语言:javascript复制1、生成的备份文件如下:
[postgres@PostgreSQL01]$ ls -l t ls bk/2021-07-11/
base.tar pg_wal.tar
2、继续插入数据:
testdb=# insert into t1 select * from t1; testdb=# select count(*) from t1;
count
- 1048576
3、创建存储点:
testdb# select pg_create_restore_point('first_pt');
2021-07-11 02:07:05.782 EST [3684] LOG: restore point "first_pt" created at 0/260001E0 2021-07-11 02:07:05.782 EST [3684] STATEMENT: select pg_create_restore_point('first_pt'); pg_create_restore_point
- 0/260001E0
4、删除表:
testdb=# drop table test_copy;
5、切换日志, 同时查看归档文件的名字 :
testdb=# select pg_walfile_name(pg_switch_wal());
pg_walfile_name 00000001000000000000002A
6、关闭数据库pg_ctl stop -m fast
7、删除$PGDATA 目录下的所有文件:
rm -rf $PGDATA/*
8、恢复数据库:
tar -vxf /home/postgres/bk/2021-07-11/base.tar -C $PGDATA
9、修改 postgresql.conf 文件,添加如下一行: restore_command = 'cp /home/postgres/arch/%f %p' recovery_target_name = 'first_pt'
10、在$PGDATA 目录下创建空文件recovery.signal,这一步是关键,恢复完成后会自动删除。
touch recovery.signal
10、启动数据库: pg_ctl start
11、登录数据库执行函数: psql
postgres=# select pg_wal_replay_resume();
12、验证数据完整性:
检查发现 copy_test 表恢复回来了。
2.3 基于 recovery_target_xid 恢复方式
代码语言:javascript复制1、 使用 pg_basebackup 或者快照对数据库进行备份。
2、 查询当前的事务号(XID):
SELECT CAST(txid_current() AS text); txid_current
954
3、 创建新的表:
testdb=# create table t6_956 as select * from t1; testdb=# create table t6_957 as select * from t1;
4、 切换几个日志:
testdb=# select pg_switch_wal();
pg_switch_wal - 0/56040D10
5、 关闭数据库:
pg_ctl stop -D /datadir
6、 删除$PGDATA 目录下的所有文件:
rm -rf /datadir
7、 恢复备份的数据库(这里用了快照备份的数据库):
tar -zvxf /root/pgdatadir.tgz -C /datadir
8、 编辑 postgresql.conf 文件,添加如下两行:
restore_command = 'cp /home/postgres/arch/%f %p' recovery_target_xid ='954'
9、 创建 recovery.signal 文件:
touch recovery.signal
10、启动数据库:
pg_ctl start -D /datadir
11、执行 pg_wal_replay_resume()函数:
postgres=# select pg_wal_replay_resume(); pg_wal_replay_resume
- (1 row)
12、验证数据的完整性:
在此事务号以后创建的表都没有了,已经恢复成功。
基于 recovery_target_time 恢 复 方 式 与 基 于 recovery_target_name 以 及 基 于 recovery_target_lsn(在创建存储点的时候会显示 lsn 号)恢复的方式一样。
2.4基于 time 恢复方式
(recovery_target_lsn='0/50000140')基于 lsn 恢复时的提示:PostgreSQL 快照方式备份与恢复
代码语言:javascript复制root 用户操作:
1、创建一个文件:
dd if=/dev/zero of=/var/local/pgdisk bs=1M count=2000
2、链接上一个 loop 设备:
losetup /dev/loop2 /var/local/pgdisk
3、创建卷组
vgcreate VG_PG /dev/loop2
4、创建逻辑卷
lvcreate -L 800M -n lv_datadir VG_PG
5、创建文件系统
mkfs.ext4 /dev/VG_PG/lv_datadir
6、创建挂接点mkdir -p /datadir
7、挂接:
mount /dev/VG_PG/lv_datadir /datadir
8、删除没有必要的目录rmdir /datadir/lost found
9、修改权限
chown postgres:postgres /datadir
9、把 pg 数据库的所有数据复制到 datadir(postgres 用户操作)
cp -a $PGDATA/* /datadir
10、启动 PG 数据库
pg_ctl -D /datadir start
11、创建快照备份需要的逻辑卷
lvcreate -s -n lv_datadirbackup -L 500M /dev/VG_PG/lv_datadir
12、创建快照文件系统挂接点mkdir /root/snapshot
13、挂接快照文件系统
mount /dev/VG_PG/lv_datadirbackup /root/snapshot
14、进入快照文件系统查看当前的内容,就可以看到 PG 数据库所有的数据文件。
cd /root/snapshot
ls
backup_label.old pg_dynshmem pg_multixact pg_snapshots pg_tblspc pg_xact postmaster.pid
base pg_hba.conf pg_notify pg_stat pg_twophase postgresql.auto.conf serverlog
15、基于快照做备份
tar -czf /root/pgdatadir.tgz .
16、备份结束后卸载快照文件系统cd
umount /root/snapshot
17、如果不需要,删除快照逻辑卷
lvremove VG_PG/lv_datadirbackup -f
18、使用快照备份做恢复
(postgres 用户)
pg_ctl -D /datadir stop
(root 用户)
rm -rf /datadir/* chmod 755 /root
(postgres 用户)
tar -zvxf /root/pgdatadir.tgz -C /datadir/
19、创建 recovery.signal,否则只会恢复到快照备份的状态,如果创建了则会恢复到最新状态,看来这个文件是提醒 pg 要做 recovery,这一步是关键:
touch recovery.signal
20、编辑 postgressql.conf 添加如下 2 行:
restore_command = 'cp /home/postgres/arch/%f %p' recovery_target_timeline = 'latest'
21、启动数据库
pg_ctl -D /datadir start
22、验证数据的完整性:
发现快照备份后的的事务能够恢复回来。
故障排除: 1) 由于之前做了一些恢复操作,日志太多,所以把 pg_wal 目录下的日志给删除了,但是进行备份的时候就报错,无法备份:
代码语言:javascript复制pg_basebackup -D bk2 -Fp
pg_basebackup: error: could not send replication command "TIMELINE_HISTORY": ERROR: could not open file "pg_wal/0000000A.history": No such file or directory
解决方法:随便找了一个日志改名为 0000000A.history 即可正常备份。