「MySQLしか使ったことないけど、SQLiteって実用的なの?」 「レプリケーションやバックアップってどうするんだろう?」
私もかつてはそう感じていました。しかし、近年ではSQLiteを本番環境で活用することが増え、その実力に度肝を抜かれました。この記事では、私の現場経験から導き出した、SQLiteを本番環境で最大活用するための具体的なノウハウをお伝えします。
- MySQLやPostgreSQLは使用経験があるけれど、SQLiteにはまだ手を出していない方。
- 小〜中規模のプロジェクトで、コスト効率の良いデータベース運用をお探しの方。
- Edge ComputingやJamstackでの活用の可能性を模索している方。
初めてSQLiteに触れたとき、正直言って「ファイルベースのDBは信頼できるのだろうか?」と疑問に思いました。しかし、ある小規模なWebサービスプロジェクト(約10万PV/月)において、MySQLのメンテナンスコストに悩んでいたとき、SQLiteに可能性を感じ始めました。次第に、以下の点に驚かされ、開眼しました:
- 充実したレプリケーション機能
- 簡単なバックアップと復旧
- 柔軟なリモートアクセス
- 信頼性の高い性能
まず「SQLiteにどうやって接続するの?」という疑問がありますよね。実際には、クライアントの選択肢が広がっています。
// Node.jsでは、better-sqlite3がオススメです。
npm install better-sqlite3
const Database = require('better-sqlite3');
const db = new Database('database.db', {
verbose: console.log,
fileMustExist: true
});
// クライアントのオススメ選択
Node.js → better-sqlite3(驚異的なパフォーマンス)
Python → sqlite-utils(便利なCLI機能付き)
Go → modernc.org/sqlite(CGO不要で軽量デプロイ)
「SQLiteでレプリケーションなんて無理だろう」と思っていませんか?実は、「Litestream」を使用して実用的なレプリケーションが可能です。
# Litestreamのセットアップは簡単
curl -L https://github.com/benbjohnson/litestream/releases/latest/download/litestream-v0.3.9-linux-amd64.tar.gz | tar xz
sudo mv litestream /usr/local/bin/
# 設定もシンプル(litestream.yml)
dbs:
- path: /path/to/db
replicas:
- url: s3://bucket-name/db
access-key-id: YOUR_ACCESS_KEY
secret-access-key: YOUR_SECRET_KEY
🎯 実績例: 一つのプロジェクトでは、この設定により月間1,000万PVのサービスを安定して運営できました。障害時も、S3ほかから数分でリストアが可能です。
重要なデータを扱う際、ポイントインタイムリカバリ(PITR)は必須です。SQLiteでも対応可能なので安心してください!
#!/bin/bash
# 実践的なPITRバックアップスクリプト
backup_dir="/backup/sqlite"
db_file="production.db"
# WALファイルのアーカイブ(5分ごとに実行)
archive_wal() {
timestamp=$(date +%Y%m%d_%H%M%S)
sqlite3 $db_file "PRAGMA wal_checkpoint(FULL);"
cp ${db_file}-wal ${backup_dir}/wal/${timestamp}.wal
}
# ベースバックアップ(日次)
base_backup() {
timestamp=$(date +%Y%m%d_%H%M%S)
sqlite3 $db_file "PRAGMA wal_checkpoint(FULL);"
cp $db_file ${backup_dir}/base/backup_${timestamp}.db
# 7日以上古いバックアップを削除
find ${backup_dir}/base -type f -mtime +7 -delete
}
「ファイルベースのDBだから、リモートアクセスは無理なのでは…?」という心配はいりません。むしろ、意外と柔軟に対応できます。
// Express.jsを使ってAPIサーバーを構築する例
const express = require('express');
const Database = require('better-sqlite3');
const app = express();
const db = new Database('database.db');
app.get('/api/query', authenticateUser, (req, res) => {
try {
const stmt = db.prepare(req.query.sql);
const result = stmt.all();
res.json(result);
} catch (err) {
res.status(500).json({ error: err.message });
}
});
- 認証は必須です
- 実行可能なSQLの制限を必ず設けること
- 接続元IPの制限も検討しましょう
「パフォーマンスの監視はどうすれば?」という疑問に応える運用技術です。
const prometheus = require('prom-client');
// データベースサイズの監視
const dbSizeGauge = new prometheus.Gauge({
name: 'sqlite_database_size_bytes',
help: 'SQLiteデータベースのファイルサイズをバイトで表示します。'
});
// クエリパフォーマンスの監視
const queryLatencyHistogram = new prometheus.Histogram({
name: 'sqlite_query_duration_seconds',
help: 'SQLiteのクエリ遅延時間を秒で記録します。',
buckets: [0.1, 0.5, 1, 2, 5]
});
// 定期的なメトリクス収集
setInterval(() => {
const stats = db.prepare(`
SELECT page_count * page_size as total_size
FROM pragma_page_count(), pragma_page_size()
`).get();
dbSizeGauge.set(stats.total_size);
}, 60000);
💡 実例: この監視設定で、某プロジェクトでは深夜のパフォーマンス低下を事前に特定できました。原因は定期バッチ処理による断片化で、VACUUMの自動化で解決しました。
- エッジコンピューティング環境(Cloudflare、Vercelなど)
- コンテナベースのマイクロサービス
- JAMstack構成のWebアプリケーション
- 小〜中規模のWebサービス(月間1,000万PVまでの対応実績あり)
🤔 よくある質問
-
Q: 本当に本番環境で問題ない?
A: 適切なユースケースであれば全く問題ありません。私の経験では、SQLiteにすることで実際に運用が楽になりました。
-
Q: 同時接続数の制限は大丈夫?
A: 適切に設定をすれば、普段の業務で問題ないことが多いです。例えば、1秒あたり1,000クエリ程度なら安定稼働しています。
📝 最後に
SQLiteは「おもちゃのDB」ではありません。適切に使えば、多くのメリットを享受できます:
- 運用コストの大幅削減
- 障害ポイントの減少によるシンプルなシステム設計
- 高いパフォーマンス
- 柔軟なデプロイ方法
「でも、うちのケースでは…」という疑問や悩みがある方は、是非コメント欄で質問してください。私の経験からできる限り具体的にアドバイスいたします。
🔧 次回予告: 次回は、「SQLiteでのスキーマ管理とマイグレーション戦略」について具体的に解説する予定です。お楽しみに!