把 Zeabur 上的 PostgreSQL 搬到 Zenavo:恢复备份并核对数据

将 Zeabur 导出的 PostgreSQL 备份直接上传恢复到 Zenavo,了解版本、角色权限与 pg_dumpall 集群备份的处理规则,并完成数据核对与切流。

本文亦提供 English、繁體中文、日本語、Español 和 Bahasa Indonesia。

从 Zeabur 搬家时,应用服务可以通过导入模板一键建好,而数据库里的数据需要通过备份搬过来。

好消息是:Zenavo 原生支持 Zeabur 下载的 PostgreSQL 备份包,不用在本地解压、也不用自己改写 SQL。这篇文章专门讲怎么把 Zeabur 的 PostgreSQL 备份恢复到 Zenavo、核对数据并切换应用。整个项目的搬迁流程可以配合Zeabur 迁移完整指南一起看。

1. 从 Zeabur 下载备份

在 Zeabur 的 PostgreSQL 服务里下载备份,同时记下两件事:

  • PostgreSQL 的主版本号(例如 15、16 或 17);
  • 应用实际使用的数据库名称。

Zeabur 下载下来的文件通常是一个 .zip 包(有时文件名里带着 .sql.gz,但外层其实是 ZIP),里面是一份 pg_dumpall 导出的集群 SQL。保持下载下来的原始文件不动即可,Zenavo 支持直接上传 Zeabur 的 .zip 备份包,也支持普通的 .sql 和 .sql.gz。

2. 在 Zenavo 创建同版本的空数据库

在 Zenavo 的目标项目里点击 添加服务 → 数据库 → PostgreSQL,选择与 Zeabur 上相同的主版本并部署。

注意三点:

  • 主版本一致最稳妥:Zenavo 会阻止把高版本(如 PG 18)的集群备份恢复到低版本(如 PG 17);先按同版本搬过来,以后有需要再单独升级。
  • 保持目标库为空:不要先启动会自动建表的应用服务,再去恢复备份。如果应用已经建了表,集群备份恢复会因为目标库非空而报错。
  • 检查扩展:如果你的库用了 PostGIS、pgvector 等扩展,确认目标镜像包含对应扩展。

3. 上传备份并恢复

打开新建的 PostgreSQL 服务的 备份与恢复(Backup & Restore) 页,点击上传,选中第 1 步从 Zeabur 下载的备份文件,然后执行恢复。

因为 Zeabur 的备份是 pg_dumpall 集群导出,Zenavo 在恢复时会自动做以下转换(详见备份与恢复文档):

  • 将里面的应用数据库内容恢复到当前服务的数据库;
  • 自动创建备份里用到的业务角色,并保留其角色密码和行级安全策略(RLS);
  • 出于安全考虑,把 Zeabur 原有的 root 超级用户降权为无超级权限、禁止直接登录的角色,同时保留它的表和对象所有权;
  • 自动跳过系统库 template1 和 postgres。

如果一份集群备份里包含多个非系统的业务数据库,恢复会报错提示先拆分;绝大多数 Zeabur 项目只有一个业务数据库,直接上传即可。

如果恢复中途因为扩展缺失等原因报错,修好原因后建议删掉这个半成品数据库服务、重新建一个干净的 PostgreSQL 再恢复,不要在只恢复了一半的库上反复重试。

4. 核对表结构和行数

恢复完成后,点开 PostgreSQL 服务的 数据库视图(Database View),可以直接在网页上跑只读 SQL 核对数据。

先看所有的业务表是不是都在:

SELECT table_schema, table_name
FROM information_schema.tables
WHERE table_type = 'BASE TABLE'
  AND table_schema NOT IN ('pg_catalog', 'information_schema')
ORDER BY table_schema, table_name;

再挑几张核心业务表(比如用户表、订单表),跟 Zeabur 上的数据对比准确行数和最新一条记录的时间:

SELECT count(*) AS row_count, max(created_at) AS latest_created_at
FROM public.orders;

(注意不要只看系统统计视图里的估算行数 reltuples,用 count(*) 核对更准。)

5. 连接应用并完成切换

在同项目的应用服务里,把数据库连接变量指向新的 PostgreSQL 服务(数据库服务名为 postgresql 时):

DATABASE_URL=${POSTGRESQL_CONNECTION_STRING}

注意:不要继续硬编码 Zeabur 旧的 root 账号去连接,直接用 Zenavo 新数据库暴露出来的连接变量(考虑到 Zeabur 之前的安全事件,换用新数据库自动生成的新密码也更安全)。

如果你希望切换期间零数据丢失,正式切流时按这个顺序操作:

  1. 先用一份当前备份在 Zenavo 上演练一遍恢复,确认应用连上后登录、查询、新建记录都正常;
  2. 挑选低峰期,先把 Zeabur 上的应用暂停(或停掉定时任务、队列消费者,避免再有新数据写入旧库);
  3. 在 Zeabur 上打最后一份最新备份,上传到 Zenavo 恢复到一个干净的 PostgreSQL 服务中;
  4. 启动 Zenavo 上的应用并切换域名 DNS。

常见问题

恢复时报错提示目标数据库不为空(database is not empty)? 说明你的应用服务在恢复前已经连上数据库并自动执行了建表(如 Prisma / TypeORM 自动迁移)。先把应用停掉,删掉并重建一个新的 PostgreSQL 服务,先恢复备份、再启动应用。

恢复成功后,应用报错 permission denied 或登录失败? Zeabur 备份里的旧 root 超级用户会被设为禁止登录。把应用的 DATABASE_URL 改成引用 Zenavo 数据库服务的 ${POSTGRESQL_CONNECTION_STRING}(使用默认的 postgres 账号和新密码)即可。

Zeabur 下载下来的文件后缀是 .sql.gz,打不开也解压不了? 这是 Zeabur 导出时的命名问题——它实际上是一个 .zip 压缩包。不用改名也不用自己解压,直接原样上传到 Zenavo 的 备份与恢复 就能识别。

数据库恢复核对无误后,记得在 Zenavo 的 备份与恢复 里顺手开启定期自动备份。完整搬家步骤见Zeabur 迁移指南。