こんにちは、かつコーチです。
前回はSQLiteが「サーバーを持たない組み込み型DB」であることを紹介しました。
今回は、その核心であるファイルベースという仕組みをもう一歩掘り下げます。
「1つのファイルにDBが入っている」とはどういうことなのか、実際にファイルを触りながら理解していきましょう。
ファイルベースDBとは?
データベース全体が1つのファイルに収まる
SQLiteでは、テーブル定義・データ・インデックスなど、データベースを構成するすべての情報が、拡張子.dbや.sqlite3などの1つのファイルに格納されます。
ls -lh app.sqlite3
# -rw-r--r-- 1 katsu staff 24K 9 2 10:00 app.sqlite3
MySQLやPostgreSQLでは、データがサーバー内部のデータディレクトリに複雑な形式で分散して保存されており、ユーザーが直接ファイルを意識することはほとんどありません。
SQLiteは逆に、このファイル自体が「データベースそのもの」なので、コピー・移動・削除といった通常のファイル操作がそのままDB操作になります。
コピーするだけでバックアップ・複製ができる
この特性を活かすと、バックアップや環境複製が驚くほど簡単になります。
# バックアップ(DBが使用中でなければcpだけで完結)
cp app.sqlite3 app_backup_20260902.sqlite3
# 本番データを使ってローカル環境を再現
cp production.sqlite3 local_dev.sqlite3
「本番のデータをローカルで確認したい」というとき、サーバー型DBならダンプの取得・復元というひと手間が必要ですが、SQLiteならファイルをコピーするだけです。
私が個人開発のアプリでSQLiteを使っていたときも、動作確認用に本番相当のデータベースファイルをそのままローカルにコピーして検証できたのは、大きな時短につながりました。
基本の使い方
DBファイルの作成と保存場所の確認
sqlite3コマンドでファイル名を指定して接続すると、そのファイルが存在しない場合は空のDBとして扱われます。
ただし、実際にファイルとしてディスクに書き出されるのは、テーブルを作成するなど何らかの書き込みが行われたタイミングです。
sqlite3 test.sqlite3
-- この時点ではまだtest.sqlite3は0バイトの可能性がある
CREATE TABLE items (id INTEGER PRIMARY KEY, name TEXT);
-- テーブル作成でファイルに実データが書き込まれる
.exit
ls -lh test.sqlite3
「ファイルを作ったつもりが中身が空だった」と感じたら、まだ書き込みが発生していないだけというケースがよくあります。
関連ファイル:ジャーナルファイル・WALファイル
SQLiteを操作していると、本体の.sqlite3ファイルの他に、-journalや-wal、-shmといった接尾辞のファイルが一時的に作られることがあります。
ls -lh
# app.sqlite3
# app.sqlite3-journal ← トランザクション中に作られる一時ファイル
これらはジャーナルファイル(更新前の状態を退避しておき、途中で失敗したときに元に戻すための仕組み)や、後の記事で解説するWALファイルの実体です。
初めてこれを見たとき「壊れたファイルができた」と誤解しがちですが、正常な動作の一部です。
これらのファイルまで含めてバックアップ・コピーの対象にしないと、整合性が崩れる可能性がある点は覚えておきましょう。
よくあるつまずきポイント:DB使用中にファイルを直接コピーする
アプリが書き込み中にコピーして壊れたデータを掴む
❌ Before:アプリを起動したままDBファイルだけをコピーする
# アプリが起動中(=DBに書き込み中の可能性がある)のままコピー
cp app.sqlite3 app_backup.sqlite3
私が過去に、稼働中のバッチ処理と並行してこの方法でバックアップを取ったところ、app_backup.sqlite3を別環境で開いた際に一部のテーブルが読み込めないというトラブルに遭遇しました。
原因は、コピーのタイミングでジャーナルファイル(-journalまたは-wal)と本体ファイルの内容がずれてしまい、中途半端な状態のファイルを複製してしまったことでした。
✅ After:.backupコマンドやVACUUM INTOを使う
-- sqlite3コマンド内で実行する専用のバックアップコマンド
.backup app_backup.sqlite3
-- SQLの中から安全にバックアップを取る方法
VACUUM INTO 'app_backup.sqlite3';
これらはSQLite自身が整合性を保証した状態でファイルを複製してくれるため、単純なcpコマンドより安全です。
以降、私は運用中のDBに対しては必ずこの方法でバックアップを取るようにしています。
バックアップやVACUUMの詳しい使い分けは、シリーズ後半の記事で改めて解説します。
応用・一歩先の使い方:ファイルベースだからできること
ファイルベースという特性は、開発・運用のさまざまな場面で応用が効きます。
- バージョン管理との組み合わせ:小規模なマスタデータをSQLiteファイルごとGitに含める(ただし頻繁な更新には不向き)
- 配布のしやすさ:アプリのインストーラーにサンプルデータ入りのDBファイルを同梱する
- 環境の使い捨て:テストごとに新しい一時ファイルを作り、終わったら削除するだけでクリーンな環境を用意できる
# テスト用に一時ファイルとしてDBを作り、テスト後に削除する例
sqlite3 /tmp/test_$(date +%s).sqlite3 < schema.sql
サーバー型DBでは「テスト用データベースを毎回作り直す」のは意外と手間がかかりますが、SQLiteならファイル操作だけで完結します。
まとめ
この記事のポイント
- SQLiteはデータベース全体が1つのファイルに収まっている
- ファイルのコピー・移動がそのままバックアップ・複製操作になる
- 本体ファイルの他にジャーナルファイル・WALファイルが付随することがある
- 稼働中のDBファイルを直接
cpするのは危険。.backupやVACUUM INTOを使う
次に読むべき記事
ファイルベースの仕組みが分かったところで、次はSQLiteならではの独特なデータ型の扱い方を見ていきましょう。
→ 次の記事:SQLiteのデータ型と型アフィニティという独自の仕組み
タグ: SQLite, 初心者向け, 入門
