- Litestream VFSは、SQLiteデータベースを**オブジェクトストレージ(S3 など)**から直接読み取り、クエリできるようにするプラグイン形式の拡張機能
- データベース全体をダウンロードせずに、リモートバックアップファイルに対して即座にクエリでき、**ポイントインタイムリカバリ(Point-in-Time Recovery, PITR)**も実行可能
- 内部的にはLTXフォーマットを使用して変更されたページ集合を効率的に管理し、**重複ページをスキップするコンパクション(compaction)**によって復旧速度を向上
- SQLiteのVFSインターフェースを活用して読み取り動作のみを横取りし、書き込み処理は既存のLitestreamプロセスが担当
- 秒単位のバックアップとインデックス更新により、ほぼリアルタイムに近いレプリカを提供し、クラウド環境での高速なクエリ実行を支援
Litestream VFS 概要
- Litestream VFSは、SQLiteがオブジェクトストレージURLを直接データソースとして利用できるようにする機能
- SQLiteシェルで
.load litestream.so と .open file:///my.db?vfs=litestream コマンドを使って有効化
- その後、S3に保存されたバックアップファイルを基にクエリを実行可能
- データベース全体をダウンロードしなくても、リモートバックアップから直接クエリを実行できる
- 例では
SELECT * FROM sandwich_ratings クエリによって、S3に保存されたデータの一部を即座に参照
ポイントインタイムリカバリ(PITR)機能
PRAGMA litestream_time = '5 minutes ago'; コマンドにより、特定時点のデータ状態を参照可能
- 相対時間(
5 minutes ago)または絶対時間(2000-01-01T00:00:00Z)を指定可能
- これにより、**即時のポイントインタイムリカバリ(Point-in-Time Recovery)**をSQLレベルで実行
- 例では、誤った
UPDATE 実行後に5分前の状態へ戻して正常なデータを確認
LTXフォーマットとデータ圧縮
- Litestream v0.5は、**LTX(Litestream Transaction eXchange)**フォーマットを統合
- 以前のバージョンではSQLiteページ全体を転送していたが、LTXは順序付きのページ集合のみを転送
- LTXの中核は**「compaction」**機能で、復旧時に最新バージョンのページだけを選択
- 例:
1 2 3 5 3 5 4 5 5 のうち、最も右側の 5、4、3、2、1 だけを使用
- LTXはデータベース全体だけでなく、LTXファイル集合間でも圧縮可能で、これによりPITR復旧が可能になる
- LTXファイルの**トレーラー(trailer)**には各ページのオフセットインデックスが含まれており、
- ファイル全体をダウンロードせずに、S3 Rangeリクエストで必要なページだけを読み取れる
VFS 実装方式
- SQLiteの**VFS(Virtual File System)**インターフェースを利用してLitestream VFSを実装
- VFSはSQLiteのOSアクセス層を抽象化するプラグイン構造
- Litestream VFSは**読み取り(Read)**動作のみを処理し、**書き込み(Write)**は既存のLitestreamプロセスが担当
- SQLiteがページを読む際、VFSは要求されたバイトオフセットの代わりにページインデックスベースのマッピングを実行
- インデックスからファイル名、実際のオフセット、ページサイズを見つけ、S3 APIのRangeヘッダーで該当ブロックだけをダウンロード
- LRUキャッシュを実装して、頻繁にアクセスされる「ホットページ」をメモリに保持し、S3呼び出し回数を最小化
リアルタイムレプリケーションと性能
- Litestreamは1秒ごとにL0レベルバックアップを実行
- VFSはS3パスを定期的にポーリングしてインデックスを段階的に更新
- 結果として、**ほぼリアルタイムに近いレプリカ(near-realtime replica)**を生成
- データベース全体をストリーミングしなくても即座に利用可能
- この構造により、高速な起動速度と短い復旧時間を実現
活用と意義
- Litestreamはデータベースのあらゆる状態を秒単位の解像度でバックアップ保持
DELETE や UPDATE のミスがあっても、望む時点へ即座に復元可能
- オブジェクトストレージから直接クエリする構造により、エフェメラルサーバー環境でも高速に動作
- 複雑な仕組みなしにSQLiteの基本機能を活用して、シンプルかつ強力なバックアップ・復旧体系を提供
- Fly.io の内部APIでも使用されており、本番環境でも安定して運用可能
1件のコメント
Hacker Newsのコメント
自分の作ったコードが他の人の役に立っていると分かるたびに本当にうれしい
psanford/sqlite3vfs
SQLite はいつも通りに動作し、Litestream はその上で透過的に動く
つまり、SQL と SQLite pragma だけで ポイントインタイムリカバリ (PITR) を実現できる。
本番データセットに直接触れなくても過去のデータをすばやく参照できる
環境変数で S3 バケットを指定し、SQLite で
.load litestream.soの後、PRAGMA litestream_time = '5 minutes ago';で過去時点のデータをすぐに参照できるbrew install sqlite3の後、.load litestream sqlite3_litestreamvfs_initのように init 関数名を明示的に指定する必要がある"LITESTREAM_REPLICA_URL"と AWS キーの環境変数 だけ設定すればよいtemp.loadExtension("/path/to/litestream.dylib", "sqlite3_litestreamvfs_init")で拡張を読み込んだ後、file:my.db?vfs=litestreamで開けばすぐ使える.dylibファイルのパスはどうやって見つけたのか気になる私のユースケースは、S3 に保存された 読み取り専用 SQLite DB を Web サイトから直接使うこと
DB は cron ジョブなどで更新され、Web サイトは Litestream VFS を通して最新データを読み取るだけ
こういう使い方でも問題ないのか、それと Python 統合モジュールがあるのか知りたい
今は Flask アプリが Google Spreadsheet からデータを取得して SQLite に変換し、毎日更新している
私のアプリのコード
追加の Python コードなしで SQLite CLI でもそのまま動作する
外部依存は S3 だけで、SQLite とも相性がよい
ZeroFS の SQLite パフォーマンス
ncruces/go-sqlite3 のサンプルコード
環境変数なしで プログラムコードから制御でき、複数の DB を同時に扱える
ただし、
PRAGMA litestream_timeは コネクション単位で適用されるので、コネクションプール使用時は注意が必要.load litestream.soを見てすぐに ncruces/go-sqlite3 を思い出したwasm 環境でも動かすのは難しかったのか気になる
DuckDB の「DuckLake」拡張はトランザクションごとに スナップショット を作って「タイムトラベル」機能を提供する
これは Litestream VFS の PITR と似ている
OLTP ではこれを復旧機能と呼び、OLAP では「Time Travel」と呼ぶ
DuckLake は外部カタログ DB (PostgreSQL/MySQL/SQLite) を使ってマルチプロセスアクセスを調整する
一方 Litestream は S3 の 不変 LTX ファイル を通じて複数のリーダーが同時アクセスできる
どちらの世界も「共有ストレージ + メタデータ + コンパクション」という構造に収束しつつある
こうしたプロジェクト間の クロスコラボレーション がもっと増えるといい
v0.5.3 リリースノート
たとえば sqlite-vec や vss のようなベクター検索拡張を使っているとき、
Litestream で S3 にリアルタイムバックアップし、Litestream VFS でリモート参照できるのか知りたい
実際に試してみるしかなさそう