Zeabur 資料庫備份與還原:PostgreSQL、MySQL、MongoDB、Redis 實測指令

從 Zeabur 把資料庫搬出來的兩種方法:內建備份與自己 dump。每條指令都在 Docker 實際跑過,連同會踩到的錯誤訊息一起列出來。

重點

  • pg_dump 版本必須 ≥ 資料庫伺服器版本,否則會直接中止。
  • 還原到 Neon、Supabase 等代管資料庫,要加 --no-owner --no-acl,否則會出現 role "root" does not exist。
  • Zeabur 內建備份的 data.sql 只能還原到有 superuser 的資料庫,而且會把舊密碼一起還原回來。
  • MySQL、MongoDB、Redis 的指令都實測可用;Redis 只當快取的話不用搬。
這篇怎麼驗證的?(5 項實測、2 項依官方文件)
實際跑過
  • PostgreSQL 16 → 17:pg_dump -Fc / pg_restore 還原到「非 superuser」的代管型資料庫(模擬 Neon/Supabase),500 筆資料與序列都正確
  • PostgreSQL:pg_dumpall 產生的 data.sql(Zeabur 內建備份的格式)分別還原到自管與代管資料庫
  • MySQL 8:mysqldump 含 routine 與 trigger 的備份與還原
  • MongoDB 7:mongodump / mongorestore(archive + gzip)
  • Redis 7:redis-cli --rdb 匯出,並在新 Redis 載入
依官方文件撰寫、未實際操作
  • Zeabur 控制台的「備份」分頁、「Instruction」分頁:依 Zeabur 官方文件撰寫,我們沒有在 Zeabur 上操作
  • 實測用 Docker 模擬 Zeabur 的資料庫(superuser 名稱同樣設為 root),不是連到真正的 Zeabur 主機
目錄(7 節)
  1. 先知道:Zeabur 有內建備份,但不一定夠用
  2. 連線資訊在哪
  3. PostgreSQL
  4. MySQL / MariaDB
  5. MongoDB
  6. Redis
  7. 還原後必做

先知道:Zeabur 有內建備份,但不一定夠用

依 Zeabur 文件,資料庫服務的「備份」分頁按下「備份」,等幾分鐘就能下載。這個功能限付費方案,備份保留 7 天後自動刪除。

資料庫Zeabur 內建備份的格式用什麼還原
PostgreSQLpg_dumpall 產生的 .sql,包含服務裡所有資料庫psql
MySQL / MariaDB.sql,包含所有非系統資料庫mysql
MongoDB多個 .bson 檔mongorestore

我們的建議:內建備份下載一份,再用下面的指令自己備一份。 原因在 PostgreSQL 那段:要搬到代管型資料庫時,內建備份的格式會出錯。

連線資訊在哪

依 Zeabur 的 PostgreSQL 模板說明,資料庫服務的 Instruction 分頁裡,Public (External) 區塊有對外用的 Connection String 和連線指令。主機名稱長得像 hkg1.clusters.zeabur.com,連線埠是 Zeabur 分配的號碼。

結尾是 zeabur.internal 的主機名稱只能在 Zeabur 內部使用,從你的電腦連不到。

下面的指令都用 Docker 執行,本機不需要安裝資料庫工具。

PostgreSQL

1. 先確認伺服器版本

docker run --rm postgres:17 psql "postgresql://USER:PASS@HOST:PORT/DB" -tAc "show server_version"

pg_dump 的版本必須大於或等於伺服器版本。 我們用 15 版的 pg_dump 備份 16 版的伺服器,會直接中止:

pg_dump: error: aborting because of server version mismatch
pg_dump: detail: server version: 16.15 ...; pg_dump version: 15.19 ...

所以下面的映像版本(postgres:16)要換成和你伺服器相同或更新的大版本。

2. 備份(推薦用 custom 格式)

docker run --rm -v "$PWD:/out" postgres:16 \
  pg_dump "postgresql://USER:PASS@HOST:PORT/DB" -Fc -f /out/backup.dump

3. 還原到 Neon、Supabase 這類代管資料庫

代管資料庫給你的帳號不是 superuser,而 Zeabur 上資料表的擁有者是 root。直接還原會出現:

pg_restore: error: could not execute query: ERROR:  role "root" does not exist

加上 --no-owner --no-acl 就能避開,實測零錯誤,資料筆數正確,新插入的 id 也正確接續原本的序列:

docker run --rm -v "$PWD:/out" postgres:17 \
  pg_restore --no-owner --no-acl -d "新資料庫的連線字串" /out/backup.dump

用 Zeabur 內建備份的 data.sql 還原

Zeabur 文件的做法是解壓縮後執行:

psql -h 主機 -p 連線埠 -U 使用者 postgres < data.sql

我們用同樣格式(pg_dumpall)實測的結果:

  • 還原到自己管理的 PostgreSQL(有 superuser):成功,資料完整
  • 還原到代管資料庫(非 superuser):失敗,出現 ERROR: permission denied to alter role。這種情況請改用上面的 pg_dump -Fc

資安提醒: data.sql 開頭有這兩行:

CREATE ROLE root; ALTER ROLE root WITH SUPERUSER ... PASSWORD 'SCRAM-SHA-256$...';

也就是說,還原後資料庫密碼會變回 Zeabur 上的舊密碼。Zeabur 發生過資安事件,還原完請立刻改密碼:

ALTER ROLE root WITH PASSWORD '新的長密碼';

Zeabur 文件也提到,如果想保留目前的密碼,可以在還原前先刪掉 data.sql 裡的 CREATE ROLE 和 ALTER ROLE 兩行。

驗證備份(5 分鐘,強烈建議)

在本機開一個空的資料庫,把備份還原進去,確認資料表與筆數正確:

docker network create restore-net
docker run -d --name restore-test --network restore-net -e POSTGRES_PASSWORD=x postgres:17
# 等幾秒讓資料庫啟動完成
docker run --rm --network restore-net -v "$PWD:/out" postgres:17 \
  pg_restore --no-owner --no-acl -d "postgresql://postgres:x@restore-test:5432/postgres" /out/backup.dump
docker exec restore-test psql -U postgres -tAc "select count(*) from 你的資料表"

# 確認完就清掉
docker rm -f restore-test && docker network rm restore-net

為什麼不用 -p 5433:5432 開 port? 我們第一次測試就是這樣寫的,結果測試機的 5433 port 上剛好有另一個本機 PostgreSQL,備份就被還原進了那台資料庫。改用 Docker 網路,測試資料庫完全不對外開 port,就不會連錯資料庫。

MySQL / MariaDB

# 備份:--single-transaction 不鎖表;--routines --triggers 連預存程序與觸發器一起備份
docker run --rm -v "$PWD:/out" mysql:8 sh -c \
  'mysqldump -h HOST -P PORT -u USER -pPASS --single-transaction --routines --triggers DB > /out/backup.sql'

# 還原
docker run --rm -v "$PWD:/out" mysql:8 sh -c 'mysql -h 新HOST -P 新PORT -u USER -pPASS DB < /out/backup.sql'

實測:資料、1 個預存程序、1 個觸發器都完整搬過去。

MongoDB

docker run --rm -v "$PWD:/out" mongo:7 \
  mongodump --uri "mongodb://USER:PASS@HOST:PORT/?authSource=admin" --archive=/out/backup.archive --gzip

docker run --rm -v "$PWD:/out" mongo:7 \
  mongorestore --uri "新的連線字串" --archive=/out/backup.archive --gzip

實測輸出:50 document(s) restored successfully. 0 document(s) failed to restore.

Redis

大多數人只拿 Redis 當快取,這種情況不用搬,新的 Redis 跑起來會自己重建快取。如果你真的在 Redis 裡存資料(例如佇列、排行榜):

docker run --rm -v "$PWD:/out" redis:7 redis-cli -h HOST -p PORT -a PASS --rdb /out/dump.rdb

成功時會顯示 Transfer finished with success。把 dump.rdb 放進新 Redis 的資料夾(官方映像是 /data)再啟動,就會自動載入。實測 key 數量一致。

還原後必做

  • 換上新的連線字串(DATABASE_URL 之類),並換掉資料庫密碼
  • 挑幾張重要的資料表,比對筆數
  • 新平台開啟每日自動備份,並且實際下載一次,確認拿得到

常見問題

Zeabur 有內建的資料庫備份嗎?

有。資料庫服務的「備份」分頁可以下載備份,但限付費方案,備份保留 7 天。PostgreSQL 的備份是 pg_dumpall 產生的 .sql 檔。

為什麼還原時出現 role "root" does not exist?

Zeabur 上資料表的擁有者是 root,代管資料庫沒有這個角色。用 pg_restore 時加上 --no-owner --no-acl 即可,實測零錯誤。