使用 PostgreSQL 时间点恢复(Point-In-Time Recovery)的多种数据恢复技术

PostgreSQL基于时间点恢复(PITR) 自postgresql8.0之后才开始提供在线的全量物理备份。和oracle rman的原理一样,通过一个基础备份,追加日志,到达恢复至基础备份后任意一时间点的目的。pg_basebackup被用于获得一个正在运行的PostgreSQL数据库集簇的基础备份。获得这些备份不会影响连接到该数据库的其他客户端,并且可以被用于时间点恢复以及用作一个日志传送或流复制后备服务器的开始点。 阅读详情

引言

本文面向那些已经具备一定数据库经验、但希望进一步学习 PostgreSQL 基础知识的初学者。假设已在 Ubuntu 环境中正确安装 PostgreSQL,本文的全部操作基于 PostgreSQL 16(开发版本)与 Ubuntu 22.10 系统完成。文章将介绍三种常用的数据恢复方法:

  1. 恢复至最新状态。
  2. 基于日志序列号(LSN, Log Sequence Number)的恢复。
  3. 基于时间戳的恢复。

时间点恢复(Point-In-Time Recovery,简称 PITR)是一种通过重放预写日志(Write Ahead Logging,WAL)文件,将数据库恢复至指定时间点状态的技术手段。

为说明该过程,可构建两个数据库副本,在其中一个数据库中插入数据,并将生成的 WAL 文件进行归档,随后令另一数据库重放该日志文件,以实现状态同步。

此过程类似于数据库因故障导致部分数据丢失的情形,可依靠 WAL 文件将系统恢复至故障前状态。重放 WAL 文件相当于自上一次检查点起,按顺序重新执行全部数据库操作,直至指定时间点,从而实现数据库的精确恢复。

开始使用

首先,创建一个新的数据库,并建立用于存放归档文件的文件夹。

$ initdb -D data/
$ mkdir archive/

随后,编辑该数据库的 postgresql.conf 配置文件。

port = 5432
wal_level = replica
archive_mode = on
archive_command = 'cp %p $HOME/pg/archive/%f'
archive_timeout = 60

接着,复制整个数据库集群(由于此时尚未创建任何表或数据,实际上并无可备份的内容)。

$ cp -rp data/* data.backup/

启动主数据库。

$ pg_ctl -D data/ -l data.log start
$ createuser -s postgres

在数据库中插入测试数据。

$ psql -U postgres -c "create database test"
CREATE DATABASE
$ psql -U postgres -d test -c "create table t1 (id int, val text)"
CREATE TABLE
$ psql -U postgres -d test -c "insert into t1 values (1, 'hello')"
INSERT 0 1
$ psql -U postgres -d test -c "insert into t1 values (2, 'world')"
INSERT 0 1
$ psql -U postgres -d test -c "insert into t1 values (3, 'foo')"
INSERT 0 1
$ psql -U postgres -d test -c "insert into t1 values (4, 'bar')"
INSERT 0 1

检查归档目录,确认归档命令执行是否正常。若未生成归档文件,可手动触发数据库生成未完成的 WAL 文件。但需注意,未完成的 WAL 文件与已完成文件大小一致,频繁执行可能导致数据库体积快速膨胀。

$ psql -U postgres -c "select pg_switch_wal()"
 pg_switch_wal
---------------
 0/187BBC8
(1 row)

$ ls -l archive/
total 16384
-rw------- 1 tristen tristen 16777216 Apr 1 09:49 000000010000000000000001

停止主服务器。

$ pg_ctl -D data stop

编辑副本数据库的 postgresql.conf 文件,将 recovery_target_timeline 参数设置为 “latest”,以便让该副本重放 WAL 文件到最新的状态。

port = 5433
archive_mode = off
restore_command = 'cp $HOME/pg/archive/%f %p'
recovery_target_timeline = 'latest'

创建 recovery.signal 文件,用于指示数据库以恢复模式启动。

$ touch data.backup/recovery.signal

启动副本服务器,此时系统将进入恢复模式并开始重放 WAL 文件。

$ pg_ctl -D data.backup -l data.backup.log start
$ tail data.backup.log
2023-04-14 09:50:16.459 PDT [21530] LOG:  redo done at 0/2000060 system usage: CPU: user: 0.00 s, system: 0.01 s, elapsed: 0.03 s
2023-04-14 09:50:16.459 PDT [21530] LOG:  last completed transaction was at log time 2023-04-14 09:49:13.53674-07
2023-04-14 09:50:16.468 PDT [21530] LOG:  restored log file "000000010000000000000002" from archive
cp: cannot stat '/home/tristen/pg/archive/00000002.history': No such file or directory
2023-04-14 09:50:16.479 PDT [21530] LOG:  selected new timeline ID: 2
cp: cannot stat '/home/tristen/pg/archive/00000001.history': No such file or directory
2023-04-14 09:50:16.496 PDT [21530] LOG:  archive recovery complete
2023-04-14 09:50:16.497 PDT [21528] LOG:  checkpoint starting: end-of-recovery immediate wait
2023-04-14 09:50:16.513 PDT [21528] LOG:  checkpoint complete: wrote 905 buffers (5.5%); 0 WAL file(s) added, 0 removed, 2 recycled; write=0.006 s, sync=0.007 s, total=0.018 s; sync files=259, longest=0.001 s, average=0.001 s; distance=28136 kB, estimate=28136 kB; lsn=0/3000028, redo lsn=0/3000028
2023-04-14 09:50:16.515 PDT [21525] LOG:  database system is ready to accept connections

最后,检查副本数据库中的数据。

$ psql -U postgres -d test -c "select * from t1" -p 5433
 id |  val
----+-------
  1 | hello
  2 | world
  3 | foo
  4 | bar
(4 rows)

结果显示,备份已成功重放 WAL 文件,并恢复至最新的变更状态。

使用 LSN 进行时间点恢复

按照前述步骤执行操作,但在关闭主服务器之前暂停。

随后,执行命令以获取主数据库当前 WAL 文件的日志序列号(LSN, Log Sequence Number)。

$ psql -U postgres -d test -c "select pg_current_wal_insert_lsn()"
 pg_current_wal_insert_lsn
---------------------------
 0/2000060
(1 row)

将获取的 LSN 值配置到副本数据库的 postgresql.conf 文件中。

port = 5433
archive_mode = off
restore_command = 'cp $HOME/pg/archive/%f %p'
recovery_target_lsn = '0/2000060'

完成设置后,关闭主数据库,并按照前述方式执行恢复操作。

$ pg_ctl -D data stop
$ touch data.backup/recovery.signal
$ pg_ctl -D data.backup -l data.backup.log start
$ psql -U postgres -d test -c "select * from t1" -p 5433
 id |  val
----+-------
  1 | hello
  2 | world
  3 | foo
  4 | bar
(4 rows)

使用时间戳进行时间点恢复

基于时间戳的恢复方式相对复杂,因为需要明确指定数据库应恢复到的具体时间点。

在操作过程中,可参照默认示例的步骤执行,直至插入数据的阶段。

$ psql -U postgres -c "create database test"
CREATE DATABASE
$ psql -U postgres -d test -c "create table t1 (id int, val text)"
CREATE TABLE
$ psql -U postgres -d test -c "insert into t1 values (1, 'hello')"
INSERT 0 1
$ psql -U postgres -d test -c "insert into t1 values (2, 'world')"
INSERT 0 1
$ sleep 60
$ psql -U postgres -c "select now()"
              now
-------------------------------
 2023-04-14 12:54:23.160389-07
(1 row)

$ psql -U postgres -d test -c "insert into t1 values (3, 'foo')"
INSERT 0 1
$ psql -U postgres -d test -c "insert into t1 values (4, 'bar')"
INSERT 0 1
$ sleep 60
$ psql -U postgres -c "select now()"
              now
-------------------------------
 2023-04-14 12:55:23.184277-07
(1 row)

在插入数据时,可通过加入 sleep 延时命令来方便管理时间戳。同时,使用 select now() 命令获取数据库当前的时间戳。与前述步骤相同,需生成剩余的 WAL 文件,并创建用于恢复的 recovery.signal 文件。

$ psql -U postgres -c "select pg_switch_wal()"
$ pg_ctl -D data stop
$ touch data.backup/recovery.signal

在本次操作中,应在副本数据库的 postgresql.conf 文件中添加以下配置:

port = 5433
archive_mode = off
restore_command = 'cp $HOME/pg/archive/%f %p'
recovery_target_time = '2023-04-14 12:54:23'

其中,recovery_target_time 参数对应于在插入前两条数据后、插入后两条数据之前获取的时间戳。随后,启动副本服务器并查看数据内容:

$ pg_ctl -D data.backup -l data.backup.log start
$ psql -U postgres -d test -c "select * from t1" -p 5433
 id |  val
----+-------
  1 | hello
  2 | world
(2 rows)

此时,数据库中仅包含前两条数据,符合预期。接着,可将恢复时间设置为比前一次时间戳晚 1 秒,并按以下方式修改 recovery_target_time 参数:

recovery_target_time = '2023-04-14 12:54:24'

由于系统在成功完成恢复后会自动删除 recovery.signal 文件,因此需重新创建该文件:

$ touch data.backup/recovery.signal

最后,重新启动副本服务器,并按前述步骤查询表中数据:

pg_ctl -D data.backup -l data.backup.log restart
psql -U postgres -d test -c "select * from t1" -p 5433
 id |  val
----+-------
  1 | hello
  2 | world
  3 | foo
  4 | bar
(4 rows)

根据向服务器执行插入命令的速度不同,可能需要调整recovery_target_time 参数以获得理想的恢复结果。若恢复时间设置过晚,可能在日志文件中出现如下错误信息:

FATAL: recovery ended before configured recovery target was reached

该错误表明指定的恢复时间超出了可恢复范围,即时间点设置过于靠后。应将恢复时间适当提前数秒后,再次启动服务器进行恢复。

结论

至此,本文完整演示了多种数据库时间点恢复方法的实现过程。我们依次介绍了三种典型方式:基于最新时间线的恢复、基于特定 LSN(日志序列号)的恢复,以及基于指定时间戳的恢复。

不同方法适用于不同场景。熟练掌握这些恢复技术,不仅有助于提升数据库运维与管理的效率,也能在突发数据问题时,确保系统具备更高的可控性与数据安全性。

postgresql 时间点数据恢复PITR(point in time recovery) 环境准备 数据库:postgresql 11 系统:阿里云centos7 测试过程 数据库安装过程不再描述。 准备测试环境 //创建保存wal日志归档的目录,并修改目录拥有者 mkdir /usr/wallog_bk chown postgres:postgres -R wallog_bk //修改PG数据库配置文件postgresql.conf vi /usr/pgsql-11/data/po... 阅读详情

相关推荐

PostgreSQL 14 数据恢复机制解析:从WAL日志到PITR的4步实践

本文深入解析PostgreSQL 14的数据恢复机制,重点介绍从WAL日志到时间点恢复(PITR)的4步实践流程。通过详细的操作示例和配置说明,帮助数据库管理员掌握关键的数据恢复技术,确保关系数据库系统在故障场景下的数据安全与可靠性。

weixin_30905981的博客 534

Postgresql 基于时间点恢复

PostgreSQL13版本后,wal_keep_segments参数废弃了,由wal_keep_size替代此参数。编辑修改postgresql.conf。#WAL日志占用空间大小。

st780206的专栏 783

PostgreSQL:误删数据后,如何恢复到删之前的那一刻?

在 PostgreSQL 中,误删数据(如 `DROP TABLE`、`DELETE FROM ...` 无 WHERE 条件、`TRUNCATE` 等)是 DBA 和开发人员最常遇到的“灾难”场景之一。幸运的是,PostgreSQL 提供了多种机制,可在不同条件下将数据恢复到删除前的那一刻。

数据知道的博客 2482

postgres数据库时间点恢复

背景:当数据库有问题的时候,比如说被删除数据,update目带where等,需要恢复到故障时间点之前测试版本:pg14。

小新没有蜡笔 678

数据安全无忧!探索 PostgreSQL 基础备份和时间点恢复的完全指南

PostgreSQL 是一个流行的开源关系数据库管理系统(RDBMS),支持多种备份类型。备份可以使用不同的工具和方法进行,可以根据需要选择最适合的备份类型。PostgreSQL 备份是指将数据库中的数据和元数据复制到另一个位置,以便在需要恢复数据时使用。备份可以进行定期或按需执行。时间点恢复是指将数据库恢复到特定的时间点状态。这对于误删除数据或数据库被破坏的情况非常有用。PostgreSQL 支持两种时间点恢复方法:基于 PITR(点时间恢复)的恢复和基于逻辑日志的恢复。

陈书予 1万+

PostgreSQL12基于时间点恢复

PostgreSQL12基于时间点恢复

postgres实现任意时间点恢复(使用pg_basebackup)

时间点恢复

yunmu666的博客 1765

基于MATLAB/Simulink与WSL2的ROS2实时联合仿真实践

本文详细介绍了基于MATLAB/Simulink与WSL2的ROS2实时联合仿真实践。通过环境配置、PX4仿真环境搭建、自定义消息生成、Simulink通信实现及实时优化等步骤,提供了完整的无人机位置控制案例,帮助开发者实现高精度的实时联合仿真。

red88的博客 204

WAL Log Archiving and Point in Time Recovery on PostgreSQL

【代码】WAL Log Archiving and Point in Time Recovery on PostgreSQL。

allway2的博客 240

crowdcountingp2p代码复现

前面学习了一下论文:Improved Field-Based Soybean Seed Counting and Localization with Feature Level Considered该论文的模型原型由CrowdCounting-P2PNet改进而来这里先复现一下CrowdCounting-P2PNet模型,然后再学习P2PNet-Soy模型。

m0_73832962的博客 2329

形位公差标注的常见误区与优化策略

本文深入解析机械设计中形位公差标注的常见误区与优化策略,特别针对NX2406用户提供实用技巧。从标注冗余、基准选择到公差值设定等五大误区入手,结合工程图实例展示如何提升标注精度与效率,帮助工程师避免常见错误,优化设计流程,确保零件功能实现与制造可行性。

info6的博客 246

Postgresql 物理热备份 -- PITR 时间点恢复(Point In Time Recovery)

时间点恢复(Point In Time Recovery) 转载于:https://www.cnblogs.com/xibuhaohao/p/11114412.html

weixin_34319640的博客 363

用LTspice仿真Buck电路输出电容:从参数计算到波形优化的全流程演示

本文详细介绍了使用LTspice仿真Buck电路输出电容的全流程,从理论计算到波形优化。通过解析关键参数如纹波电压、瞬态响应和ESR,结合工程计算方法和LTspice仿真技巧,帮助工程师优化Buck电路设计,解决输出纹波过大和瞬态响应不佳的问题。

night的博客 852

PostgreSQL教程:物理备份与恢复(PITR-Point in time Recovery 基于归档日志将数据恢复到指定的事务id或者是指定时间点)

2、归档恢复:备份中的归档,有02:00~14:00之间的数据信息,可以基于归档日志将数据恢复到指定的事务id或者是指定时间点,从而实现数据的完整恢复。场景:每天凌晨02:00,开始做全备(PBK),到了第二天,如果有人14:00分将数据做了误删,希望将数据恢复到14:00分误删之前的状态?1、恢复全备数据,使用PBK的全备数据恢复到凌晨02:00的数据。将当前服务的数据全部干掉,按照之前的全备恢复的套路先走着。将之前的最大恢复,更换为指定的事务id恢复。6、修改data目录下的恢复数据的方式。

学亮编程手记 885

Arduino创意作品实战案例:手把手教你做温控风扇

通过这个实用的arduino创意作品,轻松实现温度感应与风扇自动控制,结合传感器与编程逻辑,打造智能散热系统,是入门者理想的arduino创意作品实践项目。

weixin_42311427的博客 610

LabVIEW与VisionMaster融合开发:从封装避坑到高效集成的实战指南

本文为LabVIEW开发者提供了一套与海康VisionMaster融合开发的实战指南。针对直接调用SDK时遇到的程序集加载失败和面向对象编程冲突等核心障碍,文章详细介绍了通过C#进行“浅封装”的解决方案,包括封装显示控件和核心功能类,并给出了在LabVIEW中高效集成、调用及资源管理的最佳实践,旨在帮助开发者稳定、高效地集成机器视觉功能。

weixin_29210727的博客 157

PostgreSQL的热备和恢复

转载:原贴 http://bbs.pgsqldb.com/index.php?t=msg&th=6233&start=0&rid=&S=1324a00658e6a322138d2b4e7788678a PostgreSQL的PITR技术(Point-In-Time-Recovery) --Seamus Dean 2005-04-11(at PostgreSQL-8.0.2 re...

hanyoud的专栏 710

Python全栈入门到实战【AI实战篇 01】DeepSeek官方API全流程实战,第一个AI项目前置必备

文章摘要 本文介绍了基于DeepSeek API开发智能助手的前期准备和基础调用流程。内容涵盖: 前期准备:访问DeepSeek官网、完成账号注册与实名认证。 API Key获取:充值并创建API Key,强调密钥安全保存的重要性。 查阅文档:定位官方接口文档中的Python调用示例。 环境配置:安装openai依赖包,配置环境变量存储API Key。 代码编写:使用Python调用DeepSeek API实现基础对话功能。 调试与验证:解决常见问题,确保API调用成功。 适合零基础开发者跟随操作,快速入门

那些看似不起波澜的日复一日,会在某天让你看到坚持的意义 3742

PostgreSQL的PITR技术(Point-In-Time-Recovery)

PostgreSQL的PITR技术(Point-In-Time-Recovery)(by linux_prog@loveopensource.com)为什么要写这篇文章?因为我看了一下,国内所有的PostgreSQL教程都没有很详细的介绍该功能,而相反,国内的Oracle文章对这块非常的看重。虽然,PostgreSQL的官方文档有一个章节是介绍这块内容的,但是写得太过理论化,没有能够留给读者很深刻

在水一方 4496

点云语义分割:使用Cylinder3D训练SemanticKITTI数据集

将该路径修改到config/semanticktti.yaml文件中的data_path节点下。下载semanticKITTI数据集的点云数据和标签,解压到一起。系统:Ubuntu18。

zhaoguanhua的博客 2604

廖雪峰Python教程[完整版]

廖雪峰的python教程整理的,已经排好版了,而且还是完整的,适合小白

pitr 原理_[转] PostgreSQL的PITR技术(Point-In-Time-Recovery)

PostgreSQL的PITR技术(Point-In-Time-Recovery)--Seamus Dean 2005-04-11(at PostgreSQL-8.0.2 release)为什么要写这篇文章?因为我看了一下,国内所有的PostgreSQL教程都没有很详细的介绍该功能,而相反,国内的Oracle文章对这块非常的看重。虽然,PostgreSQL的官方文档有一个章节是介绍这块内容的,但是...

weixin_39892842的博客 194

efm32 入门.pdf

本PDF共计22页,介绍的是操作驱动API,下载与否自己斟酌。

[转] PostgreSQL的PITR技术(Point-In-Time-Recovery)

PostgreSQL的PITR技术(Point-In-Time-Recovery) --Seamus Dean 2005-04-11(at PostgreSQL-8.0.2 release) 为什么要写这篇文章? 因为我看了一下,国内所有的PostgreSQL教程都没有很详细的介绍该功能,而相反,国内的Oracle 文章对这块非常的看重。虽然,PostgreSQL的官方文档有一个章...

weixin_30786617的博客 91

LinePhone3.2.7(android端最新版本) sip客户端

SIP客户端For android:LinePhone3.2.7(最新版本),官网地址:http://www.linphone.org/

SAP B1中文培訓教材_SDK

公司内部培训资料,对开发工具 ,DIAPI, UIAPI,Add-ON有详细解说

Postgresql - 恢复数据库到指定时间 Point-in-Time Recovery (PITR)

在有些时候需要用备份数据恢复到任意的时间点,该如何操作。###################################CentOS 7 + pg 10.4###################################1. 初始化数据库参数# 创建archive目录,并授权到postgres用户mkdir /data/archive/chown -R postgres:postgre...

chuckchen1222的博客 4226

一文了解 PG PITR 即时恢复

在数据库系统中,数据是一切的基础,数据的安全更是重中之重。但可能因为各种原因导致数据丢失或损坏,因此数据的备份和恢复便显得尤为重要。 PostgreSQL 是一个强大的开源对象关系数据库系统,经过 30 多年的积极开发,在可靠性、功能稳健性和性能方面赢得了良好的声誉。Point-In-Time Recovery(简称 PITR) 是 PostgreSQL 的基于时间点的数据恢复技术,在开启 WAL 日志归档及基础备份后,可以即时恢复用户误操作丢失的数据,为您的数据库加上一重"保险"。 本文将演示 Pos

august5291的博客 1559

postgreSQL 11.4物理备份时间点恢复

创建相关管理目录 # mkdir –p /data/pgsql/ chown –R postgres: postgres /data/pgsql/ su - postgres mkdir -p /data/pgsql/backup mkdir -p /data/pgsql/archive backup目录用来存放基础备份 archive目录用来存放归档 接下来我们修改我们的postgre...

allway2的博客 965
上一篇: Oracle 19c数据库迁移到IvorySQL 4.6实战
下一篇: 你真的知道你正在运行哪个 PostgreSQL吗?
IvorySQL
博客等级 码龄5年 745粉丝 566原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值