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 $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 恢复方式
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=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 目录下的日志给删除了,但是进行备份的时候就报错,无法备份:
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 即可正常备份。
复制