2016年1月6日水曜日

[sqlite] SQLiteのロック・トランザクション関連仕様の整理

SQLiteは共有ロック・排他ロックの仕組みを備えており、プロセス内の複数スレッド、だけでなく、プロセスをまたぐ状態でSQLが同時に発行されても適切に処理されます。
トランザクションに複数のモードが存在し、指定するモードに依って取得されるロックが変わります。さらにSQLの内容に依存してロック状態が遷移するため、複数プロセスがアクセスしたときの挙動を正確に把握できるよう、仕様を整理してみました。
(文中の「プロセス」は、正確には「プロセス、もしくはスレッド」を意味します。)

DBのロック状態の種類:

  • UNLOCKED
    • ロックされていない状態。誰も読み書きしていない。DBの初期状態。
  • SHARED
    • read可、write不可な状態。複数プロセスが同時にSHAREDロックを取得可能。複数プロセスが同時にreadできることを意味する。DBがこの状態にあるとき、他のプロセスからのwriteはもちろん不可。
  • RESERVED
    • RESERVEDロックは、プロセスが将来writeを行う予定であるが、現時点ではreadだけを行っている状態である。SHAREDロックは複数プロセスが同時に取得することができるが、RESERVEDロックを取得できるのは1プロセスに限定される。
    • PENDINGロックとの違いは、新たにSHAREDロックを取得できる点(RESERVEDロック中であれば、別プロセスが新たにSHAREDロックを取得できるが、PENDINGロック中は新たにSHAREDロックを取得することはできない)。
    • SQL実行におけるwrite処理がキャッシュ上で完結する場合は、このRESERVEDロック状態で実行される。
  • PENDING
    • PENDINGロックは、既存のSHAREDロックの解放を待ち、EXCLUSIVEロックを取得してwriteを実行しようとしている状態である。PENDINGロック状態では新たなSHAREDロックの取得は許可されない。ただし、既存のSHAREDロックはそれが解放されるまでは有効。
  • EXCLUSIVE
    • EXCLUSIVEロックはDBファイルへのwrite実行時に必要なロックである。あるDBファイルの中では、ただ一つのEXCLUSIVEロックだけが有効になることができる(このとき、その他の全てのロックは解放された状態になる)。
    • SQLiteは並列処理性能を最大化する目的で、EXCLUSIVEロックの取得時間を最小にするよう動作する。

参考: File Locking And Concurrency In SQLite Version 3


トランザクションの開始:

明示的にトランザクションを開始する、しないに関わらず、DBの更新ではかならずトランザクションが実行されます。
  • BEGIN TRANSACTIONなしでDBを更新するSQLを発行した場合には、内部で自動的にトランザクションが開始され、SQL実行後にコミットされる
  • BEGIN TRANSACTIONを明示的に実行した場合には、COMMITもしくはROLLBACKを実行するまでトランザクション状態が継続される

トランザクションのモード:

  • DEFERRED
    • デフォルトはこのモード。トランザクションを開始した後でも、実際にDBに対するアクセスが発生するまではどのロックも取得しない。最初のread処理でSHAREDロックを取得し、最初のwrite処理でRESERVEDロックを取得する。
    • あるプロセスがトランザクションを開始した後に、別のプロセスが新たにトランザクションを開始できる(BEGIN TRANSACTION実行後に、別のプロセスからのBEGIN TRANSACTIONが成功してしまう点には注意が必要)。
  • IMMEDIATE
    • BEGIN TRANSACTION実行時にRESERVEDロックを取得する。あるdatabase connectionにおいてIMMEDIATEトランザクションを開始した後は、他のどのdatabase connectionも、DBへのwrite、IMMEDIATE/EXCLUSIVEトランザクションの開始はできなくなる。ただし、readは可能。
  • EXCLUSIVE
    • BEGIN TRANSACTION実行時にEXCLUSIVEロックを取得する。EXCLUSIVEトランザクション開始後は、”read uncomitted” connectionを除く全てのdatabase connectionでreadが禁止される。また、EXCLUSIVEトランザクション、例外なく全てのdatabase connectionにおいてwriteが禁止される。



ロック状態とトランザクションの関係


各トランザクション開始時にどのロックが取得されて、そのロック状態がどう遷移するのかがわかりにくかったため、絵にまとめました。


以上、SQLiteの動作理解の助けになれば幸いです。

0 件のコメント:

コメントを投稿