PostgreSQL: 使用 recovery_target_lsn 恢复到目标 WAL 位置

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