拿到一个 PostgreSQL 备份文件时,我们往往只想确认几个问题:这是正确的备份吗?里面有哪些 schema 和表?目标记录是否存在?表之间如何关联?为此专门启动 PostgreSQL、创建角色和空数据库,再完整恢复一次,成本未免太高。
关键在于区分两个任务:恢复是让数据库重新投入使用,检查则是回答关于备份文件的问题。 对后者而言,命令行工具可以完成初步排查;如果需要筛选、排序、关联查询和关系图,则可以在浏览器内重放备份,而不必搭建服务器。
pg_restore 能看到什么,不能看到什么
对于 custom 或 directory 格式的归档,pg_restore 可以列出备份目录,也可以把某张表的数据打印成原始 SQL 或 COPY 文本。这适合快速确认对象是否存在。
先判断文件类型并列出归档内容:
file backup.dump
pg_restore --list backup.dump | less
只查找表、视图或指定 schema,可以继续过滤目录:
pg_restore --list backup.dump \
| grep -E 'TABLE|TABLE DATA|VIEW' \
| grep ' public '
查看某张表的数据段,而不连接 PostgreSQL:
pg_restore \
--data-only \
--table='public.orders' \
--file=- \
backup.dump \
| less
这类输出通常是 COPY 数据或 INSERT 语句。它能帮助你确认“数据大概在不在”,但不能像数据库一样可靠地执行以下操作:
- 按条件筛选几十万行数据;
- 根据时间或金额排序;
- 连接客户表、订单表和明细表;
- 调用 PostgreSQL 函数或正确处理数据库类型;
- 根据外键生成关系图。
对于 plain SQL dump,也可以使用 less、grep 或 rg 搜索对象名:
rg -n 'CREATE TABLE|COPY public\.orders|ALTER TABLE.*FOREIGN KEY' dump.sql
不过文本搜索只是线索,不等于数据库语义。带引号的标识符、不同的 dump 选项以及分段出现的约束,都可能让简单的正则表达式漏报。
在浏览器标签页里重放备份
PostgreSQL Dump Viewer 采取了不同的路线:它不是尝试用 JavaScript 模拟 SQL,而是在浏览器标签页中运行真实的 PostgreSQL,并把 dump 重放到这个临时环境里。
操作过程很短:
- 打开 Viewer;
- 选择或拖入 dump 文件;
- 从左侧数据库树中选择 schema、表或视图;
- 在 Data、Diagram 或 SQL 标签页检查内容。
文件格式根据文件头判断,而不是根据扩展名判断。因此,一个 plain dump 即使被命名为 .backup 或 .dump,仍然可以识别。打开后可以看到 schema、表、视图和行数,选择表后可以预览记录;Diagram 页面则根据恢复后的外键绘制关系。分区表只绘制一次,不会为每个分区重复生成节点。
因为背后运行的是真实 PostgreSQL,SQL 页面可以使用 PostgreSQL 自己的语法、函数和类型,而不是某个 SQL 解析器的近似实现。查询被限制为只读的 SELECT 和 WITH。
例如,假设备份中存在 sales.orders 和 sales.customers,可以把下面的查询粘贴到 SQL 页面。运行前需要按实际备份修改表名和字段名:
WITH customer_totals AS (
SELECT
customer_id,
COUNT(*) AS order_count,
SUM(total_amount) AS total_spent
FROM sales.orders
WHERE created_at >= DATE '2024-01-01'
GROUP BY customer_id
)
SELECT
c.customer_id,
c.name,
t.order_count,
t.total_spent
FROM customer_totals AS t
JOIN sales.customers AS c
ON c.customer_id = t.customer_id
ORDER BY t.total_spent DESC
LIMIT 20;
如果表名在数据库中唯一,可以省略 schema;如果多个 schema 中都有 orders,则应明确写成 sales.orders。查询结果还可以导出为 CSV 或 JSON,适合把检查结果交给其他人确认。
哪些 dump 可以直接打开
Viewer 支持以下输入:
- plain SQL dump,例如
.sql; - 使用 gzip、Zstandard 或 LZ4 压缩的 plain dump,例如
.sql.gz、.sql.zst、.sql.lz4; - 使用
pg_dump -Ft创建的 tar 归档。
它不能直接打开 custom 格式(pg_dump -Fc)和 directory 格式(pg_dump -Fd)。这两类备份需要先转换成 plain SQL:
# custom 格式
pg_restore --file=dump.sql backup.dump
# directory 格式:最后一个参数是目录
pg_restore --file=dump.sql ./backup-directory
这一步只是从归档中生成 SQL 文件,并没有连接服务器或执行其中的 SQL。生成后再把 dump.sql 放入 Viewer。
也可以用下面的方式创建几种常见格式,便于在自己的测试项目中验证流程:
# plain SQL
pg_dump --format=plain --file=app.sql appdb
# tar 归档
pg_dump --format=tar --file=app.tar appdb
# custom 归档,需要先经 pg_restore 转成 plain SQL
pg_dump --format=custom --file=app.dump appdb
pg_restore --file=app-converted.sql app.dump
浏览器方案存在明确的资源边界:整个数据库必须放进标签页约 2 GB 的内存空间,而 PostgreSQL 本身会占用其中大约三分之一。因此,多 GB 备份仍应使用真正的 PostgreSQL 服务器。PostGIS 和 pgvector 可以加载;TimescaleDB 无法加载,依赖它的对象会按名称列出。
检查未知备份时,安全边界比便利性更重要
pg_dump 文件本质上包含将被执行的 SQL。把来源不明的备份以高权限角色恢复到真实服务器,并不只是“导入一些表”。恶意 SQL 在权限足够时,可能借助 COPY ... TO PROGRAM 等能力执行系统命令或读取文件。
因此,不要为了预览一个未知备份而直接这样做:
# 不建议对来源不明的 dump 使用高权限账号执行
psql --username=postgres --dbname=important_database --file=dump.sql
浏览器 Viewer 的价值不仅是少装一个 PostgreSQL。其临时数据库位于标签页内部,没有网络、文件系统和 shell,并在关闭标签页后消失。这让“先看看里面有什么”与生产服务器隔离开来。它也提供 VS Code、Cursor 和 VSCodium 可用的编辑器版本;其中的 AI 功能可以让编辑器代理通过只读查询回答关于 dump 的问题。
需要注意,这种隔离环境不是恢复演练的替代品。它不会验证应用能否启动、权限是否正确、扩展是否完整,也不能模拟生产环境的容量、性能和运维配置。
选择工具时,可以按这个顺序
面对一个待确认的备份,可以采用分层流程:
- 只想知道有哪些对象:使用
pg_restore --list,plain SQL 则使用rg做初筛。 - 只想粗看某张表的原始数据:使用
pg_restore --data-only --table=...。 - 需要筛选、排序、JOIN、外键图或结果导出:在本地浏览器 Viewer 中运行只读 SQL。
- 文件达到多 GB,或依赖不受支持的扩展:准备隔离的 PostgreSQL 实例,并使用低权限、一次性的恢复环境。
- 准备真实恢复:再进行完整恢复演练,验证角色、扩展、约束、应用兼容性和恢复时间。
pg_restore 仍然是正式恢复的核心工具。浏览器内 Viewer 解决的是它之前的那个问题:在投入服务器、时间和权限之前,低成本地确认手里的备份究竟是什么。