先说结论:last_autovacuum 的时间落在误删之后,不能单独证明“全部可恢复”,也不能单独证明“全部没了”。真正需要确认的是目标 heap 页面发生了什么。
DELETE 提交后发生了什么
PostgreSQL 使用 MVCC。DELETE 提交后,旧 tuple 对普通查询不可见,但其物理内容通常不会立刻清零。随后发生的几件事会逐步降低恢复概率:
- VACUUM 把 dead tuple 标记为可回收;
- 页面 pruning 改变 line pointer 或 HOT 链;
- 新 INSERT/UPDATE 复用已回收空间;
- VACUUM FULL、CLUSTER 或表重写生成新的 relation 文件。
因此,“autovacuum 已运行”只是一个重要风险信号,不是最终结论。
第一时间不要做什么
不要在原生产表上边试边改。常见但不稳妥的动作包括:
- 先执行
ALTER TABLE ... SET (autovacuum_enabled=false),过很久才复制现场; - 在原库安装扩展并反复扫描;
- 执行 VACUUM、VACUUM FULL、CLUSTER、REINDEX;
- 用
pg_resetwal或手工替换 relation 文件“碰碰运气”。
优先级应该是:停止写入 → 保存完整现场 → 在副本上判断。
最少保留哪些内容
不能只拷贝目标表文件。至少保留:
- 完整 PGDATA;
- 所有外部 tablespace;
pg_wal和归档 WAL;- PostgreSQL 日志、事故时间和原 SQL;
- 精确版本、原表 DDL、编码和扩展类型;
- 条件允许时的 LVM/ZFS/云盘/SAN 块级快照。
如何分级判断
- 未 VACUUM、后续写入很少:dead tuple 仍在的机会较高,可先用
pg_dirtyread做小范围验证。 - 普通 autovacuum 已完成、写入较少:仍值得在副本上检查 heap 页面、line pointer、WAL 和 full-page image。
- autovacuum 后大量写入:旧空间更可能已被新 tuple 复用,应预期只能部分恢复。
- VACUUM FULL、CLUSTER 或重写表的 ALTER:原 relation 通常已被替换,应转查快照、旧文件、WAL 页面证据和块级镜像。
PDU 在这个场景中的位置
有经过验证的备份、快照或完整 base backup + 连续 WAL 链时,应先在隔离环境恢复或做 PITR。只有这些可靠基线不可用、但 PGDATA、关系文件、相关 WAL 或磁盘镜像等物理证据仍可读取时,PDU 才作为标准的专业离线物理恢复主流程:读取副本中的数据文件和相关 WAL,按页面和结构解释候选记录,并把主表、TOAST、歧义项和失败项分开输出。pg_dirtyread 仍适合对现有 relation 中尚未清理的不可见行做小范围辅助验证。
这里的“标准主流程”不表示 PDU 是 PostgreSQL 官方内置功能,也不表示它替代备份/PITR或保证完整恢复。PDU 不能还原已被覆盖或 SSD TRIM 丢弃、且未出现在其他可用证据中的字节。最终结果要用原主键、行数、字段、TOAST 大字段、失败清单和业务汇总验收,不能只看“导出了多少行”。
延伸阅读:https://pduzc.com/postgresql-autovacuum-after-delete-recovery
工具选择总览:https://pduzc.com/postgresql-data-recovery-tools




