研究了Postgres的库数据恢复和转移,再来研究一下PITR按时间点恢复
类比到MySQL,因为我们是运维,不是专业的DBA,所以恢复到正确数据即可
那跟阿里云以及自建的MySQL恢复一样,首先都要有一个每天的基础备份,然后类比MySQL的Binlog,Postgres这里就相当于wal。
这么类比就对了,那么恢复过程的思路是一样的:
- 首先建立一个新的实例
- 第二步把每天的基础物理全备给恢复上去
- 第三步把之后的wal日志传到新实例,恢复到指定时间点
- 第四步最后把表或库Dump下来,灌入到旧实例的新表或新库
那我们一步一步来解释:
一、每天建立一个基础备份,这样在Base基础上,只需恢复当天的wal,速度够快
建立每天的Base基础物理备份
1pg_basebackup -Ft -Pv -Xf -z -Z5 -U postgres -h localhost -p 5432 -D /pg_backup
2
3解释一下:
4 -Ft:
5 指定备份格式为 tar。
6 如果使用 tar 格式,备份会输出 tar 文件,并且不需要直接访问 PostgreSQL 数据目录。
7 -Pv:
8 -P:显示备份进度。
9 -v:启用详情模式(verbose),显示更多日志。
10 -Xf:
11 -X:控制 WAL 日志的处理方式,f 表示在备份中包含 WAL 文件(Write Ahead Logs),确保备份可以用于恢复到完整的一致状态。
12 -z:
13 启用压缩功能。
14 -Z5:
15 设置压缩级别为 5(压缩级别从 0 到 9,9 为最高压缩)。
16 -U postgres:
17 使用 postgres 用户来连接数据库。
18 -h localhost:
19 指定数据库主机为当前机器(localhost)。
20 -p 5432:
21 指定 PostgreSQL 监听端口为 5432(默认端口)。
22 -D /pg_backup:
23 将备份文件保存到指定路径 /pg_backup 中。
这样我们就在 /pg_backup 中有了备份文件,包括一个backup_manifest的文件清单,以及一个压缩包
1root@debian:/pg_backup# ls -lha
2total 1.8G
3drwxr-xr-x 3 root root 4.0K Jul 28 16:31 .
4drwxr-xr-x 20 root root 4.0K Jul 28 16:18 ..
5-rw------- 1 root root 760K Jul 28 16:21 backup_manifest
6-rw------- 1 root root 1.8G Jul 28 16:21 base.tar.gz
那这个base.tar.gz里面又都有什么呢?
1/
2├── base/ # 每个数据库的文件
3├── global/ # 全局对象(角色、权限)
4├── pg_wal/ # WAL 日志
5├── pg_xact/ # 事务状态
6├── pg_clog/ # 事务提交信息
7├── postgresql.auto.conf # 自动配置文件
8├── postgresql.conf # 主配置文件
9├── pg_hba.conf # 访问控制文件
10├── pg_ident.conf # 用户映射文件
11└── ... # 其他系统文件
我们先 ps axjf 看一把
可以看到,-D的数据目录是在/var/lib/postgresql/13/main下,那base.tar.gz里面的内容跟/var/lib/postgresql/13/main下是一样的。
二、旧实例需要建立wal的归档模式
1# ps axjf的结果中,看到配置文件是 /etc/postgresql/13/main/postgresql.conf
2# 那就修改这个配置文件
3
4# 修改以下2行
5# 启用归档
6archive_mode = on
7# WAL 日志归档路径
8archive_command = 'cp %p /path_to_archive_directory/%f'
9
10# 然后重启服务生效
11systemctl restart postgresql
以上做完后我们如果我们做了Base备份,然后wal的日志还在继续跑,那我们就需要手动触发一下wal写盘
1select pg_switch_wal();
2
3 pg_switch_wal
4---------------
5 0/13DAC308
会得到一个序列号:0/13DAC308
然后新的wal归档日志就放在:/path_to_archive_directory/目录下了,那原始的wal数据文件还在 /var/lib/postgresql/13/main/pg_wal 下
三、新实例恢复Base库和时间点:
1# 找到新实例的数据目录,一把删空,然后把base.tar.gz解压进去
2# 建恢复目录并清理旧数据
3# 将解压后的备份移到数据库实例的实际数据目录(通常位于 /var/lib/postgresql/data)。清理旧目录后执行:
4mv /pg_restore/ /var/lib/postgresql/data
5
6# 设置恢复配置文件
7# 在数据目录中创建一个名为 recovery.signal 的空文件,同时在数据目录中新增恢复目标的配置文件 postgresql.auto.conf。
8touch recovery.signal
9
10#编辑或创建文件 postgresql.auto.conf:
11vi /var/lib/postgresql/data/postgresql.auto.conf
12
13# 添加以下内容:
14# 旧实例的wal文件需要事先copy到新实例的 /path_to_archive_directory 目录下
15primary_conninfo = ''
16restore_command = 'cp /path_to_archive_directory/%f %p'
17recovery_target_time = 'YYYY-MM-DD HH:MI:SS'
18recovery_target_action = 'pause'
说明:
restore_command
:用于指定如何恢复 WAL 日志。这里的命令是从归档目录 /path_to_archive_directory/
中拷贝 WAL 日志到 PostgreSQL 数据目录。
recovery_target_time
:你希望恢复到的时间点精确到秒(UTC 时间)。
recovery_target_action
:在完成恢复到目标时间后,pause
表示暂停恢复并进入只读模式
然后开始恢复:
1# 确保 PostgreSQL 数据目录已准备好,删除目录下旧的 postmaster.pid 等文件:
2rm /var/lib/postgresql/data/postmaster.pid
3
4# 启动 PostgreSQL 服务:
5systemctl start postgresql
6
7# 确认恢复进度
8# 观察 PostgreSQL 的日志文件(通常位于 /var/log/postgresql/postgresql-X.log,具体路径根据配置文件可能不同):
9tail -f /var/log/postgresql/postgresql-X.log
10
11# 如果一切正常,你应该能看到以下内容:
12consistent recovery point reached at 0/16B6F98
13recovery stopping at specified recovery target
14
15# 退出恢复模式
16mv /var/lib/postgresql/data/standby.signal /var/lib/postgresql/data/standby.signal.bak
17
18# 退出恢复模式后,确认是只读模式
19SELECT pg_is_in_recovery();
20
21# 如果要进入可读可写的模式
22select pg_wal_replay_resume();
四、dump出新实例指定表或库的数据,然后灌回旧实例的新表或新库
这个过程就不多说了。
多说一句,可以恢复到某个时间点,事务或者wal序列号
1# 恢复到不同时间点
2# 假设第一次恢复后,你希望尝试恢复到另一个时间点,修改 postgresql.auto.conf 文件中的 recovery_target_time 然后同样重复以上步骤即可重新恢复。
3recovery_target_time = 'YYYY-MM-DD HH:MI:SS'
4
5# 以某个事务为目标:
6recovery_target_xid = '12345'
7
8#以某个 WAL 日志序列号为目标:
9recovery_target_lsn = '0/16B6F98'
总结一下:无论postgres还是mysql,一键恢复的功能,最好都是新起一个实例,然后把基础备份恢复上去,然后用binlog或wal归档日志进行恢复,然后导出数据,最后灌入到旧实例中,这样最稳妥,旧实例也不会停服务!!!