トランザクションに複数のモードが存在し、指定するモードに依って取得されるロックが変わります。さらに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の動作理解の助けになれば幸いです。
探していた情報です。ありがたいです。
返信削除コメントありがとうございます。m(_ _)m
削除お役に立てて何よりです。