PostgreSQL备份与恢复(第二章)

Posted PostgreSQLChina

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了PostgreSQL备份与恢复(第二章)相关的知识,希望对你有一定的参考价值。

作者:徐田原

1.pg_basebackup备份工具

该备份工具自动执行pg_start_backup()和pg_stop_backup()函数,而且备份速度和数据都比手动的备份快。

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)(基于时间点的恢复)

默认情况下,恢复将会一直恢复到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版本以上

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

先以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`

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 $PGDATA9、修改postgresql.conf文件,添加如下一行:restore_command = 'cp /home/postgres/arch/%f %p' recovery_target_name = 'first_pt'10、在$PGDATA目录下创建空文件recovery.signal,这一步是关键,恢复完成后会自动删除。​
touch recovery.signal
​
11、启动数据库:pg_ctl start
​
12、登录数据库执行函数:psql
postgres=# select pg_wal_replay_resume();13、验证数据完整性:
检查发现copy_test表恢复回来了。

2.3基于recovery_target_xid恢复方式

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快照方式备份与恢复

root用户操作:

1、创建一个文件:
dd if=/dev/zero of=/var/local/pgdisk bs=1M count=20002、链接上一个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
​
10、把pg数据库的所有数据复制到datadir(postgres用户操作)
cp -a $PGDATA/* /datadir
​
11、启动PG数据库
pg_ctl -D /datadir start
​
12、创建快照备份需要的逻辑卷
lvcreate -s -n lv_datadirbackup -L 500M /dev/VG_PG/lv_datadir
​
13、创建快照文件系统挂接点mkdir /root/snapshot
​
14、挂接快照文件系统
mount /dev/VG_PG/lv_datadirbackup /root/snapshot
​
15、进入快照文件系统查看当前的内容,就可以看到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
​
16、基于快照做备份
tar -czf /root/pgdatadir.tgz .17、备份结束后卸载快照文件系统cd
umount /root/snapshot
​
18、如果不需要,删除快照逻辑卷
lvremove VG_PG/lv_datadirbackup -f
​
19、使用快照备份做恢复
(postgres用户)

pg_ctl -D /datadir stop
​
(root 用户)
rm -rf /datadir/* chmod 755 /root
(postgres用户)
tar -zvxf /root/pgdatadir.tgz -C /datadir/
​
20、创建recovery.signal,否则只会恢复到快照备份的状态,如果创建了则会恢复到最新状态,看来这个文件是提醒pg要做recovery,这一步是关键:
touch recovery.signal
​
21、编辑postgressql.conf添加如下2行:
restore_command = 'cp /home/postgres/arch/%f %p' recovery_target_timeline = 'latest'22、启动数据库
pg_ctl -D /datadir start
​
23、验证数据的完整性:
发现快照备份后的的事务能够恢复回来。

故障排除:

1)由于之前做了一些恢复操作,日志太多,所以把pg_wal目录下的日志给删除了,但是进行备份的时候就报错,无法备份:

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即可正常备份。

以上是关于PostgreSQL备份与恢复(第二章)的主要内容,如果未能解决你的问题,请参考以下文章

postgresql数据备份与恢复

PostgreSQL技术分享公开课:备份恢复与Point-in-Time Recovery(PITR

postgresql学习笔记备份与恢复

postgresql使用pg_basebackup备份与恢复

PostgreSQL备份与恢复(第三章)

PostgreSQL备份与恢复(第一章)