1428 字
7 分鐘

SQLite 搭配 Litestream:先驗證還原,再把 S3 複寫接進部署流程

SQLite 適合單一寫入節點的小型服務,但「資料庫是一個檔案」不等於只要把檔案複製出去就完成備份。若服務跑在可被重建的容器或 VM 上,真正要先確認的是:新節點沒有資料庫時,能不能從遠端副本恢復;服務運行後,複寫程序是否看的是同一個檔案。

Litestream 可以把 SQLite 的變更複寫到 S3 或相容物件儲存。本篇聚焦一個實用的工作流:先用還原演練證明副本可用,再把複寫放進正式啟動順序。它不是多寫入節點或高可用資料庫的替代方案。

先決定:這是不是單一寫入節點的問題#

這個組合適合應用程式與 SQLite 檔案放在同一個持久化磁碟區,且只有一個主要寫入程序的情況。Litestream 的角色是災難復原:將資料庫變更複寫到遠端副本;它不會讓兩個應用程式節點同時安全地寫入同一份 SQLite。

如果你已經需要跨節點同時寫入、資料庫故障自動切換,或讀寫要分離,先把這些需求列成架構條件,再比較受管資料庫或其他複寫設計。不要因為備份看起來正常,就把它當成高可用。

用同一個資料庫路徑,避免「有複寫但複錯檔案」#

Litestream 的設定以資料庫絕對路徑為準。把它與應用程式的 DATABASE_URL 集中在同一組環境變數,能降低兩邊指到不同路徑的風險。官方設定檔也支援 sqlite://sqlite3:// 前綴,因此可直接把應用程式使用的 URL 帶給 Litestream。

以下示範使用 S3 相容端點;實際 bucket、endpoint 與憑證請換成自己的值,並將金鑰放在部署平台的環境變數,不要提交到 repository。

/etc/litestream.yml
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 sh
set -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 自己的檢查確認內容可開啟。

Terminal window
set -eu
rm -f /tmp/app-restore-check.db
litestream 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 保護既有資料,將強制覆寫保留給停機後、有備份與明確目標路徑的程序。

參考資料:

Litestream:Configuration File

Litestream:Replicating to Amazon S3

Litestream:Command: restore

SQLite 搭配 Litestream:先驗證還原,再把 S3 複寫接進部署流程
https://laplusda.com/posts/sqlite-litestream-s3-recovery-workflow/
作者
Zero
發佈於
2026-07-18
許可協議
CC BY-NC-SA 4.0
這篇文章有幫助嗎?

回報錯字、失效連結,或告訴我你想看的延伸主題。