AndroidプロジェクトでORMLiteを使用しています。Sqliteがファイルレベルのロックを処理することを私は知っています。多くのスレッドが読み取り可能で、1つが書き込み可能です。ロックは複数の書き込みを防ぎます。あるスレッドがレコードを更新し、別のスレッドがこのレコードを読み取ろうとした場合にどうなるかを誰かに説明してもらえますか?(読み取ろうとしている)スレッドは古いデータを取得しますか?または、最初のスレッドが書き込み操作を完了するまでロックされますか?私が知っているように、4つのトランザクション分離レベルがあります:シリアル化可能、繰り返し可能読み取り、コミットされた読み取り、コミットされていない読み取り。そして、SQLiteまたはORMLiteでそれを変更する方法はありますか?
2 に答える
SQLite には 5 つの異なるロック レベルがあります - http://www.sqlite.org/lockingv3.html : アンロック、共有、予約、保留、排他。この質問の重要なロックは共有ロックです。
「SHARED - データベースは読み取り可能ですが、書き込みはできません。任意の数のプロセスが同時に SHARED ロックを保持できるため、多数の同時読み取りが可能です。ただし、他のスレッドまたはプロセスは、1 つまたはより多くの共有ロックがアクティブです。」
ロックはテーブル レベルです (したがって、DB 内の単一の行で何かを実行している間は、テーブル全体がロックされます)。
したがって、データを選択している間は、他のプロセスがデータを変更することはできません。データを読み取るためのロック手順は、UNLOCKED → PENDING → SHARED → UNLOCKED (トランザクションで select を実行できます) です。したがって、何かを選択していて、誰かがデータを変更するという状況は起こり得ません。
あなたの質問は、データベースを更新していて、同じテーブルで選択を行うとどうなるかです。自動コミット モードでは、書き込み/更新のロック メカニズムは、UNLOCKED →PENDING →SHARED →RESERVED →PENDING →EXCLUSIVE →UNLOCKED です。排他ロックの間、新しいリーダー (接続) はデータベースに接続できません。一度に存在できる EXCLUSIVE ロックは 1 つだけです。次に、SQLite は、接続の読み取りからの他のすべての PENDING ロックが解放されるまで待機し、新しいものを防ぎます。この時点で、データの書き込みが開始されます。
したがって、私の答えは、更新プロセスが終了していない限り、他のプロセスはもちろん古いデータを取得するということです。データの不整合が発生しないように、必ずトランザクションで更新を実行してください。SQLite は ACID に準拠しているため、部分的に更新されて一貫性のないデータが取得される状況は発生しません。
これに関する優れた本は、「SQLite の決定版ガイド」、特にトランザクションの章です。
SQLite は、コンパイル時と実行時に選択可能ないくつかの異なる分離レベルをサポートしています。
Android の SQLite はデフォルトでシリアライズモードになっていると思います。マルチスレッド アクセスに関しては、ファイル システム レベルで読み取り/書き込みロックを実行して、複数のリーダーを許可しますが、一度に 1 つのライターのみを許可します。
ただし、ORMLiteはデータベースへの単一の接続を維持するように強くお勧めします。そのため、ロックの問題は関係ない可能性があります。
より具体的には、あるスレッドがレコードを更新し、別のスレッドが読み取りを行っている場合、それは競合状態です。読み取りスレッドは、更新前または更新完了後にレコードを取得します。ただし、リーダーは部分的に更新されたデータを取得しません。しかし、あなたはそれを知っていたと思います。
SQLite でサポートされている分離レベルに関しては、前述のようにデフォルトはSerializedですが、少なくともある程度はread-uncommittedをサポートしているようです。
ORMLiteのDao.executeRaw()メソッドを使用して有効にすることができます。
dao.executeRaw("PRAGMA read_uncommitted = True;");
ただし、これについては経験がなく、同じクエリで複数回アクセスされた場合に更新された行の一貫したビューが得られるかどうかもわかりません。書き込みトランザクション中の一貫したビューと関係があるかもしれません。
この同様の質問を読んだ後、同じクエリで複数回アクセスされた場合、テーブル内の行の同じビューが保証されるかどうかわかりません。