1. ホーム
  2. android

[解決済み] AndroidでSQLiteを使用する際に、並行処理の問題を回避するにはどうすればよいですか?

2022-03-14 15:24:45

質問

AndroidアプリでSQLiteデータベースのクエリを実行する際のベストプラクティスは何でしょうか?

AsyncTaskのdoInBackgroundからinserts、deletes、selectクエリを実行しても問題ないですか?それともUI Threadを使用すべきですか?データベースクエリはquot;heavy"であり、アプリをロックする可能性があるのでUIスレッドを使用すべきではないと推測します - 結果として アプリケーションが応答しない (ANR)です。

複数のAsyncTasksがある場合、それらは接続を共有すべきですか、それともそれぞれ接続を開くべきですか?

このようなシナリオでのベストプラクティスはありますか?

解決方法は?

挿入、更新、削除、読み込みは、一般的に複数のスレッドからOKですが、Bradの 答え は正しくありません。 接続の作成方法と使用方法に注意する必要があります。 データベースが破損していなくても、更新の呼び出しに失敗する状況があります。

基本的な答えです。

SqliteOpenHelperオブジェクトは、1つのデータベース接続を保持します。 読み込みと書き込みの接続を提供しているように見えますが、実際にはそうではありません。 読み取り専用を呼び出せば、書き込み用のデータベース接続を取得することができます。

つまり、1つのヘルパーインスタンスに1つのDB接続です。 複数のスレッドから使用する場合でも、一度に1つの接続です。 SqliteDatabaseオブジェクトは、Javaロックを使用して、アクセスをシリアライズしておく。 そのため、100のスレッドが1つのDBインスタンスを持つ場合、実際のディスク上のデータベースへの呼び出しは直列化されます。

つまり、1つのヘルパー、1つのdb接続が、Javaコードでシリアライズされているのです。 1スレッドでも1000スレッドでも、1つのヘルパーインスタンスを共有すれば、すべてのdbアクセスコードはシリアルになります。 そして人生は上々です(笑)

実際の異なる接続から同時にデータベースに書き込もうとすると、1つは失敗します。 最初の接続が完了するまで待って書き込みを行うことはありません。 単に変更を書き込まないだけです。 さらに悪いことに、正しいバージョンの insert/update を SQLiteDatabase 上で呼び出さないと、例外が発生しません。 LogCatにメッセージが表示されるだけで、それでおしまいです。

では、複数スレッド? 1 つのヘルパーを使用します。 以上です。 1つのスレッドしか書き込まないことが分かっている場合、複数のコネクションを使用することができ、読み込みが速くなる可能性があります。 でも、気をつけましょう。

このブログの記事には、より詳細な情報とアプリの例が掲載されています。

Grayと私は、彼のOrmliteをベースに、Androidのデータベース実装でネイティブに動作し、私がブログ記事で説明した安全な作成/呼び出し構造に従うORMツールを実際にラップアップしています。 これはもうすぐリリースされる予定です。 見てみてください。


一応、ブログのフォロー記事もあります。

によるフォークもチェックアウトしてください。 2ポイント0 を使用することができます。