適切な保護方法を知れば、SQLiteはもはや「デモ用」ではない
SQLiteは「小規模アプリ向けデータベース」というレッレッテルを脱ぎ捨て、多くのモダンなシステムのプロダクション(本番)環境へと進出しています。肥大化したPostgreSQLクラスターに数百MBのRAMを費やす代わりに、データ全体が1つのファイルに収まる軽量なSQLiteを選ぶエンジニアが増えています。しかし、多くの人が二の足を踏む理由は依然としてこれです:「もしサーバーがダウンしたり、データベースファイルが破損したりしたら、どうやって復旧すればいいのか?」
2年ほど前、私はSQLiteを使用した小規模な在庫管理アプリを運用していました。ある晴れた朝、サーバーのハードドライブに不具合が発生し、データ書き込み中に.dbファイルが破損してしまいました。Cronジョブによる最新のバックアップは24時間前のものでした。結果として、その日の顧客の注文データがすべて消え去りました。これは過信が生んだ手痛い教訓でした。その事故の後、私はSQLiteの信頼性を根本から変えるソリューション、**Litestream**に出会ったのです。
一般的なSQLiteバックアップ手法の比較
設定に取り掛かる前に、なぜLitestreamが優れているのかを理解するために、伝統的な手法を振り返ってみましょう。
1. 手動ファイルコピーまたはCronジョブの実行
スクリプトを設定して、1時間ごとや1日ごとにdata.dbファイルをGoogle DriveやS3にコピーする方法です。
- メリット: 導入が非常に簡単で、複雑な設定が不要。
- デメリット: データ紛失リスク(RPO)が非常に高い。もし最新のバックアップが午前1時で、23時にサーバーがダウンした場合、22時間分のデータを失います。また、書き込み中にコピーすると、バックアップファイルの構造が壊れる可能性があります。
2. SQLiteの.backupコマンドの使用
sqlite3 data.db ".backup 'backup.db'"コマンドを使用すると、コピー時のデータの一貫性が保証されるため、より安全です。
- メリット: バックアップファイルが常に正常な状態で、破損しない。
- デメリット: あくまでスナップショットに過ぎない。バックアップ実行の間隔にあるデータの空白期間には依然として直面します。
3. Litestream:WAL(Write-Ahead Log)のストリーミング
Litestreamは全く異なるメカニズムで動作します。決まった時間まで待って大きなファイルをコピーするのではなく、SQLiteのWALファイルを監視し、変更を一つずつ即座にS3へプッシュします。
- メリット: RPO(目標復旧時点)が1秒未満に短縮される。サーバーが「炎上」しても、失うのは最後の数ミリ秒のデータだけです。リソース消費も非常に少なく、RAMは数MB程度です。
- デメリット: アプリケーションと一緒にバックグラウンドプロセス(サイドカー)を動かし続ける必要がある。
なぜLitestreamはこれほど効果的なのか?
鍵となるのは**WAL (Write-Ahead Log)**モードです。WALを有効にすると、SQLiteはメインファイルに統合する前に、変更内容をサブファイル(-wal拡張子)に書き込みます。Litestreamは「監視カメラ」のような役割を果たし、このWALファイルを読み取って、Cloudflare R2やAWS S3にリアルタイムでデータのかけらをストリーミングします。
一番気に入っている点は、Litestreamが完全に非侵襲的であることです。Python、Go、Node.jsなどのコードを一行も修正する必要はありません。独立して動作し、アプリケーションを遅延させることなく外部からデータベースを保護します。
Cloudflare R2を使用した実践的な導入ガイド
今回のガイドでは**Cloudflare R2**を選びました。最初の10GBが無料で、特に下り転送料金(Egress fee)がかからないため、AWS S3と比較して大幅なコスト削減が期待できるからです。
ステップ1:R2バケットの作成
Cloudflareのダッシュボードから、R2 -> Create bucket(名前をmy-sqlite-backupにする)にアクセスします。その後、Edit権限を持つAPIトークンを作成し、後で使用するためにAccess Key IDとSecret Access Keyを保存しておきます。
ステップ2:サーバーへのLitestreamのインストール
UbuntuやDebianサーバーの場合、数行のコマンドで最新版をインストールできます:
wget https://github.com/benbjohnson/litestream/releases/download/v0.3.13/litestream-v0.3.13-linux-amd64.deb
sudo apt install ./litestream-v0.3.13-linux-amd64.deb
ステップ3:litestream.ymlの設定
/etc/litestream.ymlに設定ファイルを作成します。ここでデータの「ソース」と「レプリカ(保存先)」を定義します。
access-key-id: YOUR_R2_ACCESS_KEY_ID
secret-access-key: YOUR_R2_SECRET_ACCESS_KEY
databases:
- path: /var/www/app/data.db
replicas:
- url: s3://my-sqlite-backup.YOUR_ACCOUNT_ID.r2.cloudflarestorage.com/db
ヒント: Gitで設定を管理している場合、このファイルに直接キーを貼り付けないでください。機密情報の漏洩を防ぐために、環境変数を使用しましょう。
ステップ4:WALモードの有効化
LitestreamはデータベースがWALモードの時のみ動作します。以下のコマンドを実行して有効化してください:
sqlite3 /var/www/app/data.db "PRAGMA journal_mode=WAL;"
ステップ5:システムの運用
同期プロセスを開始するためにLitestreamを起動します:
sudo systemctl enable litestream
sudo systemctl start litestream
すべてがスムーズに進んでいるか確認するために、ログをチェックします:
journalctl -u litestream -f
データ復旧プロセス(Restore)
バックアップは備えですが、実際に事故が起きた時に生き残れるかどうかはリストアのスキルにかかっています。古いサーバーが故障した際、新しいサーバーを立てて、以下のコマンドを1つ実行するだけで全データを復旧できます:
litestream restore -o /var/www/app/data.db s3://my-sqlite-backup.YOUR_ACCOUNT_ID.r2.cloudflarestorage.com/db
Litestreamは自動的に最新のスナップショットをダウンロードし、WALファイルから変更を適用して、データベースを事故直前の状態に戻します。
実戦経験と注意点
- 厳密な監視: LitestreamはPrometheus向けのメトリクス出力をサポートしています。ストリーミングが5分以上中断された場合にアラートが飛ぶように設定しましょう。
- コスト管理: S3のストレージは安価ですが、アプリが頻繁にデータを書き込む場合、多くのWALファイルが生成されます。コストを最適化するために、
retention(保持期間)を7〜30日程度に設定することをお勧めします。 - 定期的な演習: 火事になってから消火器を探してはいけません。月に一度は、空の仮想サーバーにデータをリストアしてみて、手順が常に有効であることを確認しましょう。
- Dockerでの展開: Litestreamをサイドカーコンテナとして実行できます。しかし、最も簡単な方法は、アプリのイメージに一緒にインストールして
supervisordで管理することです。
SQLiteとLitestreamの組み合わせは、コストをほぼゼロに抑えつつ、絶対的な安心感をもたらします。中小規模のプロジェクトを運営しているなら、SQLiteの利便性を享受しつつ、データ紛失の恐怖から解放されるこのコンボをぜひ試してみてください。

