sqliteのスレッドセキュリティと同時実行


SQLiteスレッドのセキュリティと同時実行
SQLiteとスレッドSQLiteはスレッドが安全です.
スレッドモデルSQLiteは、次の3つのスレッドモデルをサポートします.
  • というモデルでは、すべての反発ロックが無効になり、同じ時間に1つのスレッドしかアクセスできません.
  • というモデルの下で、1つの接続が同じ時間に1つのスレッドだけで使用されるのは安全です.
  • はすべてのロックをオンにし、自由にアクセスできます.

  • スレッドモデルの設定SQLiteは、スレッドモデルの設定を以下の3つの方法で行うことができ、実際のアプリケーションではいずれを選択してもよい.
  • このパラメータによるコンパイラの設定によりスレッドモデル
  • を選択する.
  • SQLITE_THREADSAFE呼び出し によりsqlite3_config()の初期化時に設定
  • を行うことができる.
  • SQLite呼び出し インタフェースによりデータベース接続のデータベースモデル
  • を指定する.
    SQLite同時およびトランザクション
    取引
    トランザクションはsqlite3_open_v2()のコアコンセプトです.データベースの操作(ほとんど)は、トランザクションとしてパッケージ化されてコミットされます.ここでのトランザクションのパッケージ化は自動的にオンになります.たとえば、SQLiteサイクル文にfor個のデータをデータベースに単純に挿入すると、10個のトランザクションが自動的に生成されることを意味します.しかし、トランザクションは非常に時間がかかります.一般的に、10は1秒あたりSQLite件のデータ挿入を簡単にサポートできますが、1秒あたり数十件のトランザクションしかサポートできません.一般に、トランザクション速度はディスク速度に制限されます.したがって、バッチ挿入時に自動コミットを無効にし、50000でトランザクションにパッケージ化することを考慮する必要があります.
    ロールバックモードとWAL
    書き込みが正しいことを保証するために、BEGIN ... COMMITは、トランザクションを使用してデータベースの書き換えを行うときに、現在のデータベース・ファイルをコピーするバックアップ、すなわちSQLiteを作成し、トランザクションが失敗したり、予期せぬロールバックが必要になったりした場合に、バックアップ・ファイルの内容をデータベースに復元し、同時にログを削除します.これはデフォルトのrollback journalモードです.
    その後、DELETESQLiteモード、すなわちWALを導入した.このモードでは、すべての変更が個別のWrite-Ahead Logファイルに書き込まれます.このモードでは、書き込み操作はデータベースを操作することなく、すべての読み取り操作が「書き込みと同時に」データベースファイルを直接操作し、より良い同時性能を得ることができます.
    ロックと同時実行WALは、5つのロック状態によってトランザクションを完了します.
  • SQLite、ロック状態なし.データベース・ファイルはロックされていません.
  • UNLOCKED共有状態.データベース・ファイルに共有ロックが追加されました.マルチスレッドでは読み取り操作は実行できますが、書き込み操作はできません.
  • SHARED保留状態.データベース・ファイルに予約ロックが追加されました.データベースが書き込みを行うことを示します.
  • RESERVED未決状態.データベースに書き込まれることを示し、他のリードスレッドがPENDINGロックを解放するのを待っています.あるスレッドがSHAREDロックを有すると、他のスレッドはPENDINGロックを取得できない.これにより、すべてのリードスレッドが完了し、SHAREDロックが解放されると、SHARED状態に入ることができる.
  • EXCLUSIVEパーソナルロック.データベースに書き込むことができることを示します.この状態になると、他のスレッドはデータベースファイルにアクセスできません.そのため、同時性のために、その保有時間は短いほど良い.

  • 1つのスレッドは、低レベルのロックがある場合にのみ、より高いレベルのロックを取得できます.
    /*
    ** Lock the file with the lock specified by parameter eFileLock - one
    ** of the following:
    **
    **     (1) SHARED_LOCK
    **     (2) RESERVED_LOCK
    **     (3) PENDING_LOCK
    **     (4) EXCLUSIVE_LOCK
    **
    ** Sometimes when requesting one lock state, additional lock states
    ** are inserted in between.  The locking might fail on one of the later
    ** transitions leaving the lock state different from what it started but
    ** still short of its goal.  The following chart shows the allowed
    ** transitions and the inserted intermediate states:
    **
    **    UNLOCKED -> SHARED
    **    SHARED -> RESERVED
    **    SHARED -> (PENDING) -> EXCLUSIVE
    **    RESERVED -> (PENDING) -> EXCLUSIVE
    **    PENDING -> EXCLUSIVE
    **
    ** This routine will only increase a lock.  Use the sqlite3OsUnlock()
    ** routine to lower a locking level.
    */
    

    まとめ
    以上のように、データベースのセキュリティを確保するには、一般的に次のようなパターンを採用することができます.
  • EXCLUSIVEは単一スレッドモデルを採用し、専用のスレッド/キュー(同時に1つのタスクしかアクセスできない)で
  • にアクセスする.
  • SQLiteはマルチスレッドモデルを採用し、各スレッドはそれぞれのデータベース接続(すなわちSQLite)
  • を使用する.
  • sqlite3 *はシリアルモデルを採用し、すべてのスレッドが同じデータベース接続を共通に使用します.

  • 書き込み操作の同時性が悪いため、マルチスレッドがアクセスする際には実際には互いに待つ必要があり、読み取り操作に必要なSQLiteロックは共有可能であるため、最高の同時性を保証するために推奨される
  • マルチスレッドモード
  • を使用
  • SHAREDモード
  • を用いる.
  • シングルスレッド書き、マルチスレッド読み(各スレッドはそれぞれ対応するデータベース接続を持つ)
  • 長時間トランザクションの回避
  • キャッシュWALコンパイル結果
  • 多文sqlite3_prepareBEGINを通じて表示トランザクションを行い、複数回の自動トランザクション消費量を減らす
  • .
    リファレンス
    SQLiteはスレッドが安全か
    Using SQLite In Multi-Threaded Applications
    SQLiteのマルチスレッド環境での応用
    SQLiteの挿入が遅すぎます
    SQLite自動コミット
    YapDatabase wikiの詳細