2026年5月17日

2026年5月17日

SQLiteをサーバーで使う方法|sqlite3の基本操作・PHPからの接続・権限・バックアップ

SQLite は、データベース全体を 1 つのファイルに保存する組み込み型のデータベースです。MySQL や PostgreSQL と違い、常駐するサーバープロセスがありません。アプリケーション(PHP や Python など)がライブラリを通してファイルを直接読み書きします。そのため「SQLite サーバーを起動する」「停止する」という作業はなく、サーバーで使うときに考えるのは、ファイルの置き場所と権限、同時に書き込むときの扱い、バックアップの 3 点です。

この記事の手順は Ubuntu 24.04(SQLite 3.45.1、PHP 8.3)で動作を確かめました(2026年11月時点)。

SQLite が向いている用途・向いていない用途

向いている 向いていない
小〜中規模のツールや管理画面のデータ 多数の利用者が同時に書き込むサービス
設定・キャッシュ・ジョブの記録 複数のサーバーから同じデータベースを使う構成
ログの一時集計、開発・検証用のデータベース ネットワークファイルシステム(NFS など)上での運用

SQLite は読み取りを同時に処理できますが、書き込みはデータベース全体で一度に 1 つずつです。書き込みが集中するサイトでは MySQL や MariaDB を選びます。

手順 1: sqlite3 コマンドを入れる

操作用のコマンドラインツール sqlite3 を入れます。

# Ubuntu / Debian
sudo apt update
sudo apt install sqlite3

# RHEL / AlmaLinux / Rocky Linux / Fedora
sudo dnf install sqlite

# 版の確認
sqlite3 --version

libsqlite3-dev(Debian 系)や sqlite-devel(RHEL 系)は、C のプログラムをコンパイルするときに使う開発用ファイルです。コマンドで操作するだけなら不要です。

PHP から使う場合は、PHP の SQLite 拡張も入れます。Ubuntu では php-sqlite3 パッケージに sqlite3 拡張と pdo_sqlite 拡張の両方が含まれます。

sudo apt install php-sqlite3
php -m | grep -i sqlite

pdo_sqlite と sqlite3 が表示されれば使えます。Web サーバー経由の PHP(PHP-FPM など)には、サービスの再起動後に反映されます。

手順 2: データベースを作って操作する

sqlite3 にファイル名を渡すと、そのデータベースを開きます。ファイルがなければ、最初にテーブルを作った時点で作られます。

sqlite3 app.db

sqlite> というプロンプトが出たら、SQL を入力します。SQL の文は ; で終わります。

CREATE TABLE users (
  id INTEGER PRIMARY KEY,
  name TEXT NOT NULL,
  email TEXT UNIQUE
);
INSERT INTO users (name, email) VALUES ('Alice', 'alice@example.com');
SELECT * FROM users;

SQL とは別に、. で始まる「ドットコマンド」で sqlite3 自体を操作します。ドットコマンドの末尾に ; は付けません。

コマンド 内容
.tables テーブルの一覧
.schema users テーブルの定義(CREATE 文)
.mode box 結果を罫線つきの表で表示(.mode column も可)
.headers on 列名を表示
.dump データベース全体を SQL 文として出力
.backup ファイル名 データベースを別ファイルにバックアップ
.quit 終了

シェルから 1 行で実行することもできます。スクリプトや cron で使う場合はこの形が便利です。

sqlite3 app.db "SELECT COUNT(*) FROM users;"
sqlite3 app.db ".tables"

手順 3: PHP(PDO)から接続する

PHP では PDO を使うと、MySQL と同じ書き方で扱えます。データベースのファイルが公開ディレクトリ(ドキュメントルート)の外にある例です。

<?php
// データベースファイルは公開ディレクトリの外に置く
$dbFile = '/var/lib/myapp/app.db';

$pdo = new PDO('sqlite:' . $dbFile, null, null, [
    PDO::ATTR_ERRMODE            => PDO::ERRMODE_EXCEPTION,
    PDO::ATTR_DEFAULT_FETCH_MODE => PDO::FETCH_ASSOC,
    PDO::ATTR_TIMEOUT            => 5, // ロック待ちの秒数
]);
$pdo->exec('PRAGMA journal_mode = WAL');
$pdo->exec('PRAGMA foreign_keys = ON');

$pdo->exec('CREATE TABLE IF NOT EXISTS users (
    id INTEGER PRIMARY KEY,
    name TEXT NOT NULL,
    email TEXT UNIQUE
)');

// 値はプレースホルダーで渡す(SQL インジェクション対策)
$stmt = $pdo->prepare('INSERT INTO users (name, email) VALUES (:name, :email)');
$stmt->execute([':name' => 'Bob', ':email' => 'bob@example.com']);

$stmt = $pdo->prepare('SELECT id, name, email FROM users WHERE email = :email');
$stmt->execute([':email' => 'bob@example.com']);
print_r($stmt->fetch());
  • PDO::ATTR_TIMEOUT は、ほかの処理が書き込み中でロックが取れないとき、何秒まで待つかの設定です。指定しないと、すぐに「database is locked」のエラーになりやすくなります。
  • PRAGMA journal_mode = WAL は、書き込みの最中も読み取りを止めない「WAL モード」に切り替えます。設定はデータベースファイルに保存されるので、一度実行すれば以後も有効です。
  • PRAGMA foreign_keys = ON は接続ごとに必要です。SQLite は既定では外部キー制約を確認しません。

手順 4: ファイルの置き場所と権限を決める

Web サーバー(PHP)から SQLite を使うときに、つまずきやすいのが権限です。

  • ドキュメントルートの外に置く: /var/www/html/data.db のように公開ディレクトリに置くと、URL を知られた時点でファイルごとダウンロードされるおそれがあります。/var/lib/myapp/ のような公開されない場所に置きます。
  • ディレクトリにも書き込み権限が要る: SQLite は書き込みのときに、データベースと同じディレクトリに一時ファイル(app.db-journal、WAL モードでは app.db-wal と app.db-shm)を作ります。ファイルだけ書き込み可能にしても、ディレクトリに書き込めないと失敗します。

ディレクトリが root の所有で、ファイルだけ www-data の所有にした状態で書き込むと、次のエラーになりました。

SQLSTATE[HY000]: General error: 8 attempt to write a readonly database

PHP-FPM や Apache が www-data ユーザーで動いている場合(Ubuntu / Debian の既定)の設定例です。

sudo mkdir -p /var/lib/myapp
sudo chown www-data:www-data /var/lib/myapp
sudo chmod 750 /var/lib/myapp
# 既存のファイルを置く場合
sudo chown www-data:www-data /var/lib/myapp/app.db
sudo chmod 640 /var/lib/myapp/app.db

RHEL 系の Apache や PHP-FPM は既定で apache ユーザーで動きます。実際のユーザーは ps aux | grep -E 'php-fpm|httpd|apache2' の 1 列目(親プロセスではなく子プロセスの行)で確認してください。SELinux が有効な環境では、ディレクトリに書き込み用のラベル(httpd_sys_rw_content_t など)も必要です。

手順 5: 同時書き込みとロックの扱い

  • 書き込みは一度に 1 つです。別の処理が書き込み中だと、待ち時間(手順 3 の PDO::ATTR_TIMEOUT)を過ぎた時点で「database is locked」になります。
  • WAL モードにすると、書き込みの最中でも読み取りは止まりません。Web アプリケーションでは WAL モードが向いています。
  • 長いトランザクションはロックを長く持ちます。まとめて書き込むときは 1 つのトランザクションにして、短時間で終えます。
  • SQLite の公式ドキュメントでは、WAL モードはネットワークファイルシステム上では動かないとされています。データベースはサーバーのローカルディスクに置きます。

手順 6: バックアップと整合性の確認

書き込み中のデータベースを cp でコピーすると、途中の状態がコピーされたり、WAL モードでは -wal ファイルの内容が抜けたりして、壊れたバックアップになることがあります。SQLite の機能でコピーします。

# 方法 1: .backup コマンド(オンラインバックアップ API を使う)
sqlite3 /var/lib/myapp/app.db ".backup /backup/app-$(date +%Y%m%d).db"

# 方法 2: VACUUM INTO(SQLite 3.27.0 以降。不要な領域を詰めたコピーを作る)
sqlite3 /var/lib/myapp/app.db "VACUUM INTO '/backup/app-vacuum-$(date +%Y%m%d).db'"

# バックアップが壊れていないか確認(ok と表示されれば正常)
sqlite3 /backup/app-$(date +%Y%m%d).db "PRAGMA integrity_check;"

VACUUM INTO の出力先は、存在しないファイルか空のファイルでなければエラーになります。同じ日に 2 回実行する場合はファイル名に時刻も入れます。

SQL 文として残したい場合は .dump を使います。別の SQLite へそのまま読み込めます。

sqlite3 /var/lib/myapp/app.db .dump | gzip > /backup/app-$(date +%Y%m%d).sql.gz
# 復元
gunzip -c /backup/app-20261110.sql.gz | sqlite3 /var/lib/myapp/restored.db

cron で毎日バックアップを取る場合は、.backup の行をスクリプトにして、古いファイルを削除する処理と一緒に登録します。

SQLite と WordPress

WordPress 本体が公式に必要とするデータベースは MySQL か MariaDB です。WordPress.org が公開している「SQLite Database Integration」プラグイン(2026年11月時点で 3.1.3)を使うと SQLite で動かせますが、プラグインの説明では、本番で使う場合は確実なバックアップを取ること、書き込みが多いサイトでは MySQL や MariaDB のほうが向くことが書かれています。有効にすると空の新しいデータベースが作られ、既存の記事は移されません。ローカルの開発環境での使い方は「WordPressのSQLiteドライバーで軽量なローカル開発環境を作る方法」を参照してください。

よくある質問

SQLite のサーバーを起動・停止するにはどうすればよいですか

その必要はありません。SQLite にはサーバープロセスがなく、アプリケーションがファイルを開いたときだけ使われます。nohup sqlite3 … で常駐させたり、kill で止めたりする手順は不要です。

エラーのログはどこに出ますか

SQLite は自分ではログファイルや syslog に書きません。エラーは使っているアプリケーションに返されるので、PHP なら PHP のエラーログ(PHP-FPM のログや Web サーバーのエラーログ)を見ます。

「database is locked」が頻繁に出ます

ロック待ちの時間(PDO::ATTR_TIMEOUT、sqlite3 コマンドなら .timeout 5000)を設定し、WAL モードにし、長いトランザクションがないかを確認します。それでも頻発するなら、書き込みの量が SQLite の向く範囲を超えている可能性があり、MySQL などへの移行を検討します。

まとめ

  • SQLite はサーバープロセスを持たない、1 ファイルのデータベースです。sqlite3 コマンドで SQL とドットコマンドを使って操作します。
  • PHP からは PDO(sqlite: で始まる DSN)で接続し、ロック待ちの時間と WAL モードを設定します。
  • Web サーバーで使うときは、ドキュメントルートの外に置き、ファイルとディレクトリの両方を実行ユーザーが書き込めるようにします。バックアップは cp ではなく .backup か VACUUM INTO で取ります。

関連記事:

参考: SQLite – Command Line Shell For SQLite、SQLite – Write-Ahead Logging、SQLite – Temporary Files Used By SQLite、SQLite – VACUUM、PHP マニュアル – PDO_SQLITE、WordPress.org – SQLite Database Integration

更新履歴: 2026-11-10 全面改訂(存在しない「SQLite サーバーの起動・停止」の手順、シェルと SQL が混在したコード例、syslog でのログ確認を削除し、PHP からの接続、権限、ロック、バックアップの手順に置き換え)。

お気軽にご相談ください

お見積りへ お問い合わせへ
▲