ARTICLE DETAIL

资讯详情

深耕网站建设、视觉设计与SEO优化的一线实战洞察。

备份之外,PostgreSQL的数据恢复还能怎么做

备份之外,PostgreSQL的数据恢复还能怎么做

本文整理于 HOW 2026 演讲内容,演讲者:张晨,PostgreSQL ACE Partner、PDU 项目作者。

当备份失效、数据库无法启动、数据字典损坏,PostgreSQL的数据恢复还能怎么做?PDU(PostgreSQL Data Unloader)给出了一个工程化的答案。

一、备份恢复:不可动摇的第一选择

在数据库生态中,备份恢复始终是最可验证、最可持续的数据恢复模式。无论是逻辑备份还是物理备份,恢复链路和恢复结果都可以事先演练,风险可评估;它不是一个一次性的抢救动作,而是可以长期纳入制度的常态化能力。无论工具、文档还是运维规范,备份恢复都是默认的首选答案。

然而,备份恢复并非万能。

备份的边界主要体现在三个方面:

第一,完整性仍要自担。 备份文件本身是否完整、链路是否可用,最终仍要由用户自己保证。逻辑备份出来的dump文件一旦损坏,常规途径无法恢复;二进制归档文件同样如此。

第二,恢复粒度偏粗。 像PITR(Point-In-Time Recovery)这样的方案通常面向全库或实例级恢复。当面对单表误操作时,恢复的代价往往过高——为了恢复个别数据而将整个数据库回退,在生产环境中几乎不可接受。

第三,恢复窗口受限。 真实生产故障里,业务中断时长、恢复路径和操作代价经常彼此冲突。大规模恢复动作的时间窗口,往往超出了业务所能承受的范围。

当备份失效,或者备份无法满足恢复目标时,非常规恢复就不再是“可选项”,而是“最后手段”。这也是所有数据库都会在极端场景下抛给DBA的真正难题。

二、PostgreSQL生态中的常见非常规工具及其局限

在PostgreSQL开源生态中,确实存在一些可用于非常规恢复的工具,但它们更多是在某一环解决问题,而非提供完整的恢复链路。

pg_filedump 可以直接从数据文件导出数据,绕过数据库内核。但它的使用前提是必须已知表结构,且通常只能逐表处理。一旦遇到复杂数据类型或文件结构异常,工具本身就可能卡住。

pg_dirtyread 可以读取尚未被Vacuum清理的“脏数据”——即那些被标记为dead但尚未真正清除的残留数据。但问题在于,一张生产表中往往存有大量脏数据,该工具无法精准筛选所需数据,需要人工甄别,效率低下。

WalMiner 可以从WAL日志中解析SQL,更偏向日志侧的追踪与回放。但它的适用范围与场景受限,且需要深度学习才能掌握,一旦出现问题,用户必须具备自行修改代码的能力。

这些工具各有价值,但都面临一个共同的问题:它们是孤立的“点工具”,而非完整的“恢复链路”。

三、一个真实且棘手的故障场景

让我们看一个真实的案例。

环境: PostgreSQL 13.6,1TB+生产库。

故障: 个别磁盘损坏,导致部分系统表无法正常读取。执行\dn命令时无法正常显示模式——这意味着该模式下的所有表都无从查起。在数据库内核层面,这些表已经处于“不可见”状态,数据存在丢失风险。

传统抢救路径的复杂性:

在这种场景下,传统思路只能绕过PostgreSQL内核,直接从数据文件做抢救。这类似于Oracle生态中的DUL(Data Unloader)思路,但在PostgreSQL里并没有一个现成的“一把梭”工具。

抢救的第一步,不是导出业务表,而是先拿回数据字典

具体而言,需要从数据文件中定位并导出四张核心字典表——pg_classpg_typepg_attributepg_namespace。其中,pg_class用于识别哪些记录对应主表、索引和TOAST表;pg_type用于确定列的真实数据类型;pg_attribute用于恢复列名、列顺序、列属性;pg_namespace用于将对象重新挂回正确的Schema语义。

但把四张字典表导出来,只是拿回了“原材料”。真正难的是把它们重新组合成完整的库结构。你必须重新回答这些问题:pg_class里哪些记录代表数据主表,哪些又是TOAST表?TOAST表和主表如何建立关联?filenodetablename如何一一对应?pg_attribute里的列名如何挂回正确的表?数字类型号最终对应到什么真实数据类型?

最起码的目标,是要形成一份或多份“表名+表结构”的文件。只有形成这份结构描述,后续的数据导出工作才有抓手。

而这才仅仅是字典恢复阶段。对于1TB级的生产库,不可能靠人工逐表恢复。pg_filedump以单表操作为主,大库表多、对象关系复杂,反复手工执行既慢也容易出错。真正的难点是把这些单表操作封装成可重复执行的工程化能力——支持批量导出、支持重复执行、把专家经验沉淀成可操作流程。

更严峻的是,pg_filedump本身存在已知短板:当主表的TOAST字段中的TOAST filenode与实际TOAST文件不一致时,工具会解析失败;遇到jsonbbytea、PostGIS等复杂数据类型时同样无能为力。一旦pg_filedump在单表导出过程中遇到边界问题,你就必须具备修改其内核代码的能力——否则面对真实数据文件,只能望“数据文件”兴叹。

四、PDU:把极端恢复变成工程化能力

正是在这样的背景下,PDU(PostgreSQL Data Unloader)应运而生。

PDU是什么?

PDU是一款专业级、开源的PostgreSQL数据库灾难恢复和数据提取工具,支持PostgreSQL 9至18版本,可以直接读取PostgreSQL数据文件,无需运行中的数据库实例。

一句话理解:它是灾难恢复、取证分析和紧急数据提取的终极解决方案。核心目标不是“替代数据库”,而是在数据库打不开的时候,继续把数据捞出来。

和传统工具的差异: PDU不是只解决某一个恢复环节,而是把初始化、字典恢复、结构浏览、按库/模式/表导出串成一条可执行链路。

工具组成: 一个可执行文件pdu,再加一个配置文件pdu.ini——面向灾难恢复场景的最小运行形态。

在上述故障场景中,PDU的处理逻辑可以概括为两步:

第一步:初始化。pdu.ini中配置PGDATA路径,执行初始化命令即可自动生成数据字典。初始化完成后,就可以像在数据库里一样,通过\l\dn\dt查看当前的库结构。整个过程通常在3到5分钟内完成。

[root@node1 xman]#cat pdu.ini
PGDATA=/home/16pg/data
ARCHIVE DEST=/home/16pg/wal arch

2.png

第二步:数据导出。 使用use <库名>选择数据库,然后通过unload sch <模式名>按模式导出,或通过unload tab <表名>按表导出。导出阶段不再需要手工拼结构,只需要按熟悉的库、模式、表维度发出导出命令。

PDU对pg_filedump短板的系统性补强:

  • 数据类型适配:已适配jsonbbytea、PostGIS、数组类型等,并可按客户需求紧急开发。
  • 复杂文件场景:针对生产数据库中的复杂数据文件场景做过深入测试与代码完善。
  • 效率与并行:通过自主生成TOAST索引、8路并行解析,把超长TOAST数据和整体救援效率尽可能拉高。

PDU的价值,不是替代备份。它真正重新定义的,是极端场景下PostgreSQL数据恢复的工程化能力——备份仍然是第一选择,PDU负责“备份之外,怎么办”

五、真实客户案例验证

PDU的价值不是概念验证,而是已经在真实客户场景里完成过高压恢复。

案例一:地理信息历史归档库磁盘损坏。 \dn无法显示模式,涉及大量PostGIS数据。PDU在48小时内完成1.5TB生产数据导出,并处理了jsonb与PostGIS的相关问题。这48小时包含了现场代码修复的时间——发现问题、紧急修复、完成导出,一气呵成。

案例二:PG系国产数据库数据目录被rm -rf删除。 用户首先通过专业手段恢复出数据文件,但这些文件已无法直接挂载使用。PDU快速适配后,4小时内全部导出并验证无误。

案例三:Windows上PostgreSQL 9.6被加密勒索。 每个数据文件均被加密,在无法拿到完整数据字典的情况下,通过测试环境的DDL还原表结构,并利用PDU恢复核心表数据。

这三个案例分别代表了三类典型场景——大库灾难恢复、国产数据库适配、极端勒索软件场景。而所有这些恢复经验,都已经集成并融合到PDU的工具能力中。

六、结语

在过去,PostgreSQL的极端场景恢复高度依赖DBA对内核数据结构的深入理解、对pg_filedump等工具的熟练掌握,以及临场修改代码的能力。这是一条门槛极高、不可复用的路径。

PDU所做的,正是将这条路径工程化——把过去依赖专家经验和内核知识的恢复流程,做成可执行、可复用、可标准化的工具。

备份永远是第一选择。 但当你面对“备份之外,怎么办”这个问题时,PDU提供了一个专业级的答案。

PDU已在GitHub开源,感兴趣的用户可直接下载编译并在测试环境中验证。具体获取方式可关注相关公众号及开源仓库。

返回列表