由 John Doe 八月 4, 2025
你想要恢复数据库到指定的 WAL 位置吗?PostgreSQL 可以轻松地做到这一点。
时间点恢复
在执行时间点恢复时,PostgreSQL 提供了多种方式来停止恢复或在特定点停止 WAL 重放,通过不同的方式来指定停止点:
- 时间戳,使用 recovery_target_time。
- 名称,使用 recovery_target_name,这是用户通过
pg_create_restore_point()
定义的恢复目标。 - 事务 ID,使用 recovery_target_xid,恢复将进行到分配此 ID 的事务提交为止。
- “immediate”,这是一种特殊情况,使用
recovery_target = 'immediate'
。使用此方式,恢复将在服务器达到一致状态时停止。
重放位置还会受到 recovery_target_inclusive 的影响,其默认值为 true,恢复相关的参数列表见此处。
示例
今天给大家介绍的是一种恢复到 WAL 位置的目标类型:
逻辑序列号 LSN 是 WAL 流中的一个位置,简而言之,它是一组用于确定记录插入位置的标识,例如 “0/7000290”。使用 recovery_target_lsn 参数,用户可以在记录级别设置恢复的终止位置。这在很多情况下都非常有用,最常见的情况是,例如 WAL 在某个特定记录处损坏,用户希望尽可能多地重放数据。使用这个参数,无需深入分析 WAL 段来确定目标对应的事务 ID 或时间,只需将其设置为某个记录的位置即可。用户甚至可以通过 SQL 接口查看这样的 LSN 位置,例如使用pg_current_wal_lsn()
可以获取服务器当前使用的 LSN 位置。
我们通过一个小示例来说明,假设有一个已经进行过基础备份的实例(设置全量备份是能够向前重放的重要前提):
CREATE TABLE data_to_recover(id int);
INSERT INTO data_to_recover VALUES (generate_series(1, 100));
SELECT pg_current_wal_lsn();
pg_current_wal_lsn
--------------------
0/3019838
(1 row)
在这种情况下,插入到实例中的数据使用的 WAL 截止到 LSN 位置 “0/3019838”。现在我们再插入一些数据:
INSERT INTO data_to_recover VALUES (generate_series(101, 200));
SELECT pg_current_wal_lsn();
pg_current_wal_lsn
--------------------
0/301B1B0
(1 row)
这会添加更多数据,消耗几个额外的记录。确保最后一个 WAL 段已归档:
SELECT pg_switch_wal();
现在,我们要恢复到插入前 100 条元组的位置,可以在 postgresql.conf 中设置以下参数:
recovery_target_lsn = '0/3019838'
restore_command = 'cp /path/to/archive/%f %p'
创建恢复触发文件,并启动数据库进行恢复:
$ touch recovery.signal
$ pg_ctl start
时间点恢复完成后,日志中将显示类似以下的条目(然后恢复暂停):
LOG: recovery stopping after WAL location (LSN) "0/3019838"
登录到该节点后,确实只有 100 条元组:
SELECT count(*) FROM data_to_recover;
count
-------
100
(1 row)
非常不错的体验,希望这个特性能帮助到你。
参考
提交日志:https://git.postgresql.org/pg/commitdiff/a0ffa885e478f5eeacc4e250e35ce25a4740c487