1
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

【SQLite】ネットワーク上のDBファイルでWALが危険な理由と安全なPRAGMA設定まとめ

1
Posted at

はじめに

本記事では、ネットワーク上に配置したSQLiteのDBファイルで
WAL設定が危険な理由と、
代替となる安全な設定をまとめます。

SQLiteをネットワーク共有フォルダ上で運用しようとして
WALモードを設定したところ問題が発生したため、
設定を見直した際の記録です。


1. なぜネットワーク上のDBファイルでWALが危険なのか

WALモードの仕組みをおさらい

WAL(Write-Ahead Logging)モードは
書き込み内容を一時的に-walファイルに記録し、
キリのいいタイミングでDBファイルに反映する仕組みです。

この仕組みが正常に動作するためには
複数プロセス間で-shm(共有メモリ)ファイルを
リアルタイムに共有できる環境が必要です。

ネットワーク上では何が起きるか

ローカル環境(安全)
  プロセスA ─┐
             ├─ 共有メモリ(-shm)を直接共有 ─ DBファイル
  プロセスB ─┘

ネットワーク環境(危険)
  PC-A ── ネットワーク ── 共有フォルダの-shmファイル ── DBファイル
  PC-B ── ネットワーク ──        ↑
                          ネットワーク遅延・キャッシュの不整合が発生する
問題 内容
共有メモリが共有されない -shmファイルはローカルの共有メモリを前提としており、ネットワーク越しには正常に機能しない
ロック機構が信頼できない NFS・Samba等のネットワークファイルシステムではファイルロックの動作が保証されない
DBファイルの破損リスク 複数PCが同時に書き込んだ場合にデータが壊れる可能性がある
キャッシュの不整合 OSがファイルをキャッシュするため、他PCの書き込みがすぐに見えない場合がある

SQLite公式ドキュメントでも、ネットワークファイルシステム上での
WALモードの使用は明確に非推奨とされています。

データ破損が発生した場合、修復が困難になります。


2. 今回の設定値と理由

以下の4つのPRAGMAを設定しました。

import sqlite3

conn = sqlite3.connect(r"\\server\share\data.db")

conn.execute("PRAGMA journal_mode = TRUNCATE;")
conn.execute("PRAGMA synchronous = FULL;")
conn.execute("PRAGMA locking_mode = NORMAL;")

3. journal_mode(ジャーナルモード)

データ破損に備えて変更内容を記録する方式を設定します。

PRAGMA journal_mode = TRUNCATE;

設定値一覧

設定値 内容 ネットワーク上での安全性
DELETE 変更をジャーナルファイルに記録し、コミット後に削除する
TRUNCATE コミット後にジャーナルファイルを削除せず0バイトに切り詰める ◯(今回の設定)
PERSIST コミット後もジャーナルファイルを残す(ヘッダのみ書き換え)
MEMORY ジャーナルをメモリ上のみに保持する(クラッシュ時にデータ消失)
WAL Write-Ahead Loggingを使用する ✕ ネットワーク上では危険
OFF ジャーナルなし(ロールバック不可・最速だが危険)

TRUNCATEを選んだ理由

  • WALを使わないためネットワーク上でも安全
  • ジャーナルファイルの削除(DELETEモード)より
    ファイルの切り詰めの方がI/Oコストが低く高速
  • ファイルが残るためOS側のファイルキャッシュが再利用されやすい

4. synchronous(同期モード)

書き込みデータをどのタイミングでディスクに同期するかを設定します。

PRAGMA synchronous = FULL;

設定値一覧

設定値 内容 安全性 速度
OFF OSに任せて同期しない(最速・最も危険) 最速
NORMAL 重要なタイミングのみ同期する 速い
FULL すべての書き込みでディスクへの同期を保証する ◎(今回の設定) 遅い
EXTRA FULLより厳密に同期する(ディレクトリも同期) 最も遅い

FULLを選んだ理由

  • ネットワーク環境では書き込みの途中でセッションが切れるリスクがある
  • FULLにすることで書き込みのたびにディスクへの同期を保証
    データ破損を防ぐ
  • 速度よりデータの安全性を優先する方針

ローカル環境ではNORMALが一般的なバランス設定です。
ネットワーク環境ではFULLを推奨します。


5. locking_mode(ロックモード)

DBファイルのロックをどのように管理するかを設定します。

PRAGMA locking_mode = NORMAL;

設定値一覧

設定値 内容 ネットワーク上での挙動
NORMAL トランザクションごとにロックを取得・解放する(デフォルト) ◎(今回の設定)
EXCLUSIVE 接続している間ずっとDBファイルを占有する △ 他プロセスがアクセスできなくなる

NORMALを選んだ理由

  • EXCLUSIVEはDBを占有し続けるため
    複数PCからのアクセスができなくなる
  • NORMALはトランザクション終了後にロックを解放するため
    他のプロセスが順番にアクセスできる
  • ネットワーク環境での複数クライアントからの同時アクセスに対応するために必須

WALモードではEXCLUSIVEが実質必要になる場面が多く、
これもネットワーク環境でWALを避ける理由の一つです。


6. 設定のまとめと適用コード

設定値まとめ

PRAGMA 設定値 目的
journal_mode TRUNCATE WALを避けつつ安全に変更を記録する
synchronous FULL 書き込みのたびにディスクへの同期を保証する
locking_mode NORMAL トランザクションごとにロックを解放する

適用コード(Python)

import sqlite3


def get_connection(db_path: str) -> sqlite3.Connection:
    """
    ネットワーク上のSQLiteに安全に接続する

    Args:
        db_path: DBファイルのパス(UNCパス等)

    Returns:
        設定済みのConnectionオブジェクト
    """
    conn = sqlite3.connect(db_path)

    conn.execute("PRAGMA journal_mode = TRUNCATE;")
    conn.execute("PRAGMA synchronous = FULL;")
    conn.execute("PRAGMA locking_mode = NORMAL;")

    return conn


if __name__ == "__main__":
    db_path = r"\\server\share\data.db"

    conn = get_connection(db_path)

    # 設定確認
    print(conn.execute("PRAGMA journal_mode;").fetchone())
    print(conn.execute("PRAGMA synchronous;").fetchone())
    print(conn.execute("PRAGMA locking_mode;").fetchone())

    conn.close()

8. ローカル環境との設定比較

PRAGMA ローカル推奨 ネットワーク推奨 理由
journal_mode WAL TRUNCATE WALはネットワーク上で動作が保証されない
synchronous NORMAL FULL ネットワーク越しの書き込み途切れに備える
locking_mode NORMAL NORMAL 変更なし

まとめ

ネットワーク上のSQLiteでWALモードが危険な理由は
-shmファイルを使った共有メモリの仕組みが
ネットワークファイルシステムでは正常に機能しない
ためです。

代替設定として以下の組み合わせが有効です。

journal_mode = TRUNCATE  → WALを使わず安全にジャーナルを管理
synchronous  = FULL      → 書き込みをディスクに確実に同期
locking_mode = NORMAL    → 複数クライアントがアクセスできるよう都度ロック解放

ネットワーク環境でSQLiteを使う場合は
WALモードへの変更をしないよう注意してください。

1
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?