前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >PostgreSQL 备份与恢复(第二章)

PostgreSQL 备份与恢复(第二章)

原创
作者头像
DB之路
修改2021-07-15 18:02:18
1.9K0
修改2021-07-15 18:02:18
举报
文章被收录于专栏:数据库PG数据库PG

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

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 2. Point-in-Time Recovery
    • 2.1基于命名还原点恢复
      • 2.2基于 recovery_target_name
        • 2.3 基于 recovery_target_xid 恢复方式
          • 2.4基于 time 恢复方式
          相关产品与服务
          云服务器
          云服务器(Cloud Virtual Machine,CVM)提供安全可靠的弹性计算服务。 您可以实时扩展或缩减计算资源,适应变化的业务需求,并只需按实际使用的资源计费。使用 CVM 可以极大降低您的软硬件采购成本,简化 IT 运维工作。
          领券
          问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档