Supabase应用用了头像、发票或用户附件,备份就要同时留下数据库与文件。只有SQL,恢复后可能还看得到文件路径,却打不开附件;只有图片目录,又缺少它属于哪个用户、对应哪条记录的信息。

数据库备份到底保留了什么?

Supabase明确说明,数据库备份不包含通过Storage API保存的对象本体。因此,恢复旧数据库不会找回之后被删除的文件。可以按下面这张清单检查自己的副本,而不是只数下载了几个压缩包。

要恢复的内容应保存在哪里检查什么
业务表结构与记录SQL导出或平台数据库备份表、记录及关联关系
图片和附件本体独立Storage文件副本桶名、路径、字节内容
自定义Storage权限迁移文件或单独保存的变更普通用户能否正确访问
应用配置与函数代码项目代码和受控配置存档恢复后是否仍指向旧项目

自动每日备份覆盖Pro、Team、Enterprise项目,分别可访问最近7、14、最多30天。免费项目官方建议定期自行导出并保留站外副本。数据库备份文档还说明,Postgres 15.8.1.079及更新版本的项目默认使用物理备份;要自己持有SQL,仍可手动导出。

怎样导出可以带走的SQL?

安装Supabase CLI并启动Docker Desktop。在项目顶部的Connect面板取连接串,官方迁移流程默认使用Session pooler。把数据库密码填进去,特殊字符按连接URL规则编码。以下示例假设你已把完整连接串存入本机变量SB_BACKUP_DB_URL,不要把它提交到代码仓库。

例如先新建并进入backup-2026-09-15目录,后续命令都在此运行。按官方CLI备份流程分别导出:

supabase db dump --db-url "$SB_BACKUP_DB_URL" -f roles.sql --role-only
supabase db dump --db-url "$SB_BACKUP_DB_URL" -f schema.sql
supabase db dump --db-url "$SB_BACKUP_DB_URL" -f data.sql --use-copy --data-only -x "storage.buckets_vectors" -x "storage.vector_indexes"

这三份分别用于角色、结构和记录。查看每条命令是否成功结束,再确认文件不是空文件。不要因为schema.sql体积很小就认定备份完成:db dump参考说明,默认导出不包含数据和自定义角色。

托管的auth、storage结构也不是普通业务schema。你额外加过的触发器或RLS策略,要按迁移指南单独保存差异;迁移历史同样有单独导出步骤。本文命令不覆盖Vector Buckets的恢复。

用S3接口按桶另存文件

批量文件可用rclone读取Supabase的S3兼容接口。在项目S3配置页生成Access Key ID、Secret Access Key,并复制endpoint与region。这组密钥绕过RLS、能访问所有桶,只放在受控机器上;权限范围见官方S3认证说明。

运行rclone config,新建名为sb的remote,类型选S3、provider选Other;填入上述四项,并保留路径式访问。以下是配置字段示意,尖括号都要换成自己的值:

[sb]
type = s3
provider = Other
access_key_id = <Access Key ID>
secret_access_key = <Secret Access Key>
region = <项目region>
endpoint = <项目S3 endpoint>
force_path_style = true

字段含义可查rclone S3文档。以下假设你的桶叫avatars;目录日期只是示例,每次备份换一个新目录:

rclone copy sb:avatars ./storage/avatars --progress

其他桶逐一复制到各自目录。copy不会删除目标已有文件,但这不等于保存历史版本:同路径内容更新仍可能替换旧副本。需要比较copy与sync时,可接着看云盘复制选择。

把SQL与文件放进同一批备份

假设数据库在10:00导出,头像目录在10:10复制。有人10:05替换了u123/avatar.jpg,两份副本就可能来自不同状态。这是分开备份需要自己处理的一致性问题。

小型应用可以安排短维护窗口,暂停会修改业务表或上传文件的入口,包括后台任务和Webhook写入,完成两部分备份后再恢复写入。同时存一份清单,写明数据库导出起止时间、各桶复制时间和失败对象。高写入业务不能用这个小例子代替一致性方案,必须设计与业务事务相容的恢复策略。

清单里可给每一批备份一个相同编号。例如“九月十五日早间”对应三个SQL文件和两个文件桶,不把前一天的附件混进这一批。复制失败的对象应列出完整路径,重试成功后再把这批标为完成。存放副本的机器还要有足够空间,容量估计以实际文件总量为准,不能只看数据库用量。

把自动任务接上Push心跳监控时,应在SQL和所有桶复制都成功后发送成功信号。只监控脚本启动,会把“运行过”误当成“已备份”。

恢复后怎样确认附件真的回来了?

用独立项目演练,安装Postgres客户端psql,按官方恢复步骤导入角色、结构和数据。新项目使用了哪些扩展、是否使用Vault加密或Realtime,要走对应分支;启用过的Webhooks、非默认扩展也要在新项目配置;自定义登录角色的密码需要重新设置。

文件通过Storage接口补回相同桶和对象路径,桶的公开属性与权限也要恢复。上面的本地目录保存了文件内容,但不是完整项目迁移包。以头像桶为例,选一条用户记录,找到其对象路径,下载文件并与副本比较;再用普通登录用户读一次。S3管理密钥能读到文件,不能证明用户权限正确。

私有附件至少检查“所有者能下载、其他用户被拒绝”这两个结果。还要检查应用配置中的项目URL,避免数据库已经切换,图片请求仍指向旧项目。相关部署工作可放进工具栈清单。这里未运行真实项目恢复,不能给出恢复耗时;下一次备份是否可信,要由这次演练中的SQL导入、文件内容和用户访问结果共同决定。