PostgreSQL 表被 DROP TABLE,事务又已经提交,不能再靠 ROLLBACK 撤销。这个时候先不要重建同名表,也不要在原盘上反复启动、写入或安装恢复工具。释放后的磁盘块一旦被新数据覆盖,后面的恢复工具也无法把原字节重新生成出来。
先查备份、快照和 PITR 条件
“没有备份”经常只是没有 pg_dump。还要检查事故前是否存在:
pg_basebackup、pgBackRest、Barman 等物理备份;- 云盘、虚拟机、存储阵列或文件系统快照;
- 可以作为恢复起点的 base backup,以及从该起点开始连续可用的归档 WAL。
只要这些恢复基线可用,优先在隔离集群恢复到 DROP TABLE 之前,再导出目标表。不要直接把生产库整体倒回去,也不要把只有一批 pg_wal 文件误认为完整的 PITR 条件。
没有可用恢复基线时,先保全物理证据
DROP TABLE 提交后,目标 relation 的目录项和系统字典映射通常已经消失,但底层磁盘块不一定立即被清零。能否恢复取决于旧页面是否还留在磁盘、文件系统或存储层,是否已经被新写入复用,以及能否找到匹配的 PostgreSQL 版本、DDL、TOAST 和表空间信息。
事故现场应先做这些事:
- 停止数据库、应用、批处理和同一存储上的新增写入;
- 保存完整 PGDATA、全部表空间、
pg_wal、归档 WAL、日志、配置和准确版本; - 对原盘、云盘或虚拟磁盘制作块级镜像;
- 后续检查和恢复只在副本上进行,输出写到新的存储位置。
pg_dirtyread 需要目标 relation 仍然存在,通常不能直接扫描 DROP TABLE 后已经变成未分配空间的磁盘块。pg_filedump、pageinspect 可以帮助检查已经找到或仍存在的页面文件,但不会自动完成裸盘碎片搜索、catalog/TOAST 关联和整批结果验收。
PDU 在 DROP TABLE 恢复中的位置
当事务回滚、经过验证的备份、快照和 PITR 都不可用,但 PGDATA 副本、旧 relation、相关 WAL 或块级磁盘镜像仍可读取时,PDU 应作为标准的专业离线物理恢复主流程。
这套流程不是在原库里执行一条“撤销 DROP”的 SQL,而是在只读副本上完成:
- 确认 PostgreSQL 大版本、小版本、页面大小、编码和原表 DDL;
- 从数据文件、表空间或磁盘镜像中识别候选 PostgreSQL 页面;
- 按 relation、页面结构和字段布局解析候选 tuple;
- 分开处理主表记录、TOAST 大字段、重复候选、归属歧义和失败页;
- 把可解析结果导出到新位置,再按主键、时间范围、字段、行数和业务汇总验收。
候选页面数量不等于已恢复业务行数,能够解析 tuple 也不等于已经重建原表的全部逻辑关系。相同字段布局的页面可能存在归属歧义,索引、约束和序列还需要依据 DDL 与业务规则重建或核对。
能恢复多少,取决于现场还剩什么
影响结果的主要条件包括:
DROP TABLE后是否继续写入或重建同名对象;- 存储是否启用了 TRIM、discard、自动回收或即时清零;
- 原表和 TOAST 页面是否已经被覆盖;
- 原表 DDL、PostgreSQL 版本、编码和扩展类型是否准确;
- 表空间、WAL、日志和块级镜像是否完整保留;
- 业务侧是否有主键范围、总账、报表或其他可用于验收的基准。
PDU 不是 PostgreSQL 官方内置功能,也不替代备份或 PITR。它能处理的是仍然存在的物理证据,不能恢复已经被覆盖、被 SSD TRIM 丢弃,且没有出现在其他副本或 WAL/FPI 中的字节。因此,任何 DROP TABLE 案例都不应预先承诺 100% 完整恢复。
相关资料:




