SQLite 搭配 Litestream:先驗證還原,再把 S3 複寫接進部署流程
SQLite 適合單一寫入節點的小型服務,但「資料庫是一個檔案」不等於只要把檔案複製出去就完成備份。若服務跑在可被重建的容器或 VM 上,真正要先確認的是:新節點沒有資料庫時,能不能從遠端副本恢復;服務運行後,複寫程序是否看的是同一個檔案。
Litestream 可以把 SQLite 的變更複寫到 S3 或相容物件儲存。本篇聚焦一個實用的工作流:先用還原演練證明副本可用,再把複寫放進正式啟動順序。它不是多寫入節點或高可用資料庫的替代方案。
先決定:這是不是單一寫入節點的問題
這個組合適合應用程式與 SQLite 檔案放在同一個持久化磁碟區,且只有一個主要寫入程序的情況。Litestream 的角色是災難復原:將資料庫變更複寫到遠端副本;它不會讓兩個應用程式節點同時安全地寫入同一份 SQLite。
如果你已經需要跨節點同時寫入、資料庫故障自動切換,或讀寫要分離,先把這些需求列成架構條件,再比較受管資料庫或其他複寫設計。不要因為備份看起來正常,就把它當成高可用。
用同一個資料庫路徑,避免「有複寫但複錯檔案」
Litestream 的設定以資料庫絕對路徑為準。把它與應用程式的 DATABASE_URL 集中在同一組環境變數,能降低兩邊指到不同路徑的風險。官方設定檔也支援 sqlite:// 與 sqlite3:// 前綴,因此可直接把應用程式使用的 URL 帶給 Litestream。
以下示範使用 S3 相容端點;實際 bucket、endpoint 與憑證請換成自己的值,並將金鑰放在部署平台的環境變數,不要提交到 repository。
dbs: - path: ${DATABASE_URL} replica: url: s3://my-backup-bucket/my-service/app.db?endpoint=https://s3.example.com access-key-id: ${AWS_ACCESS_KEY_ID} secret-access-key: ${AWS_SECRET_ACCESS_KEY}先檢查環境變數展開Litestream 預設會展開設定檔中的
$VAR與${VAR}。若值本身含有美元符號,應先確認展開後內容;需要停用時可使用-no-expand-env。這不是密碼管理的替代品,金鑰仍應由執行環境注入。
啟動順序:只在「本機不存在」時還原
一個可重建的部署流程通常分成三步:建立資料目錄、只有首次或磁碟遺失時還原、最後才啟動應用程式與持續複寫。-if-db-not-exists 能讓既有的本機資料庫保持原樣;若遠端還沒有任何副本,-if-replica-exists 可讓初始化流程正常結束。
#!/usr/bin/env shset -eu
mkdir -p /data
litestream restore \ -if-db-not-exists \ -if-replica-exists \ /data/app.db
exec litestream replicate \ -exec "./start-app.sh" \ /data/app.db這個範例故意不在啟動時使用 -force。官方文件指出,還原預設不會覆寫已存在的非空資料庫或 SQLite sidecar 檔案;這個保護能避免部署腳本把仍在使用的資料檔取代掉。需要強制還原時,應在停機、確認目標路徑與保留一份原始檔後,改用獨立的復原指令處理。
把「能還原」變成可重跑的演練
複寫日誌顯示成功,只能證明程序曾嘗試上傳;最有價值的檢查是把副本還原到新的暫存檔,再用 SQLite 自己的檢查確認內容可開啟。
set -eu
rm -f /tmp/app-restore-check.dblitestream restore \ -dry-run \ -o /tmp/app-restore-check.db \ s3://my-backup-bucket/my-service/app.db
litestream restore \ -o /tmp/app-restore-check.db \ s3://my-backup-bucket/my-service/app.db
sqlite3 /tmp/app-restore-check.db 'PRAGMA quick_check;'先跑 -dry-run,可以看到預計取回的副本與交易範圍,但不會寫入檔案。正式還原時刻意指定 /tmp 的新路徑,避免碰到目前服務使用中的資料庫。PRAGMA quick_check 的輸出應為 ok;若不是,保留該檔案與 Litestream 輸出,先查明副本或應用程式寫入流程,再考慮清理。
上線前至少記錄這四件事
| 檢查 | 要確認的結果 |
|---|---|
| 路徑 | 應用程式、Litestream 設定與持久化磁碟區都指向同一份資料庫 |
| 遠端副本 | 用實際部署身分可列出或還原指定的 replica URL |
| 還原演練 | 能還原到新路徑,並通過 SQLite 檢查 |
| 復原權限 | 緊急時執行者有讀取副本、停服務與更換資料檔的必要權限 |
也別忘了資料庫以外的狀態:使用者上傳檔、環境變數、遷移紀錄與金鑰輪替策略,不會因為 SQLite 已複寫而自動被備份。若服務部署在 Zeabur,服務層的日誌、PORT 與環境變數排查可參考 Zeabur 服務異常時先查什麼;資料庫復原則應獨立演練。
真正值得留下的完成條件不是「Litestream container 正在跑」,而是「我今天能把遠端副本還原到全新路徑,且知道不會覆寫正式資料檔」。
常見問題
Q: Litestream 可以取代 PostgreSQL 嗎?
A: 不應直接這樣判斷。它為 SQLite 提供遠端複寫與還原流程,適合單一主要寫入節點的災難復原。若需求是多個應用程式節點同時寫入、故障自動切換或跨節點交易協調,應另外評估資料庫架構。
Q: 為什麼不直接在啟動時加 -force 還原?
A: -force 的效果是明確允許覆寫既有非空目標;它適合受控的復原作業,不適合預設的日常啟動路徑。一般啟動以 -if-db-not-exists 保護既有資料,將強制覆寫保留給停機後、有備份與明確目標路徑的程序。
參考資料:
回報錯字、失效連結,或告訴我你想看的延伸主題。