SQlite: ошибка блокировки базы данных

Я использую архитектуру SOA для своего приложения для Android. Я постоянно запускаю службу в фоновом режиме (каждую минуту), которая извлекает данные из моей базы данных MYSQL и синхронизирует их с моей базой данных SQLite (если есть какие-либо изменения в двух базах данных).

Теперь, когда служба работает в фоновом режиме, она открывает файл SQLite. В то же время, если я обрабатываю (использую) приложение, оно также пытается открыть Sqlite для получения данных. В этом случае я получаю сообщение об ошибке: База данных заблокирована на android.database.SQLiteOpenHelper.getReadableDatabase.

Кто-нибудь может подсказать, что можно сделать в такой ситуации?


person Neha    schedule 14.12.2011    source источник
comment
Согласно вашему предложению, я создал один экземпляр DatabaseHelper (который является классом-оболочкой) следующим образом: частный статический экземпляр DatabaseHelper; общедоступный статический синхронизированный DatabaseHelper getHelper (контекстный контекст) { if (instance == null) instance = new DatabaseHelper (context); вернуть экземпляр; } Теперь всякий раз, когда мне нужно использовать методы DatabaseHelper, я вызываю их следующим образом: DatabaseHelper db = DatabaseHelper.getHelper(this); БазовыйОбъект bObj = db.GetObjectFromDB(GlobalObject1);   -  person Neha    schedule 28.12.2011
comment
Теперь этот GetObjectFromDB является методом из DatabaseHelper. Этот метод считывает данные из Sqlite DB. Для этого мне нужно получить доступ к БД, и я делаю это следующим образом: SQLiteDatabase db=this.getReadableDatabase(); Как было сказано ранее, мое приложение выполняет много потоков. Когда один из моих потоков обращается к БД, другой поток также пытается получить доступ к БД, используя тот же метод GetObjectFromDB. Моя проблема в том, что getReadableDatabase() всегда открывает новое соединение с БД. Как я могу преодолеть это состояние. Спасибо, Неха   -  person Neha    schedule 28.12.2011
comment
Привет всем, я получил ответ на свой вопрос. Я сделал статический экземпляр DataBasehelper (который является классом-оболочкой) и статический экземпляр SQLiteDatabase: частный статический экземпляр DatabaseHelper; частная статическая база данных SQLiteDatabase sqlitedb=null; общедоступная синхронизированная база данных SQLiteDatabase getHelper() { if (sqlitedb == null) { sqlitedb = this.getWritableDatabase(); } else if (sqlitedb.isOpen() == false) { sqlitedb = this.getWritableDatabase(); } вернуть sqlitedb; } Теперь я вызываю БД следующим образом: SQLiteDatabase db = this.getHelper();   -  person Neha    schedule 29.12.2011


Ответы (4)


Вам необходимо совместно использовать одно соединение с базой данных между вашим приложением и фоновой службой. Это позволит правильно сериализовать все обращения к базе данных.

person Graham Borland    schedule 14.12.2011

Я предпочитаю использовать здесь ContentProvider.

Несмотря на то, что в основном он предназначен для обмена между приложениями, его можно использовать внутри нашего отдельного приложения.

Если мы используем контент-провайдера, не нужно беспокоиться о закрытии и блокировке базы данных.

Обратитесь к Simple Content Provider для операций с БД

person Labeeb Panampullan    schedule 14.12.2011

SQlite — это файловая база данных, предоставляющая доступ только одному приложению за раз.

  1. Вы должны либо синхронизировать свою службу с вашим приложением, чтобы служба давала приложению некоторое время для получения новых данных (в этом есть много решений; ищите семафоры, мониторы и циклический перебор).

  2. Вы используете вторую службу, которая будет получать запросы на ввод-вывод к базе данных от вашей службы и приложения, ставить их в очередь, выполнять запрошенный ввод-вывод и возвращать любые результаты приложению или службе, отправившей запрос.

person Vosobe Kapsimanis    schedule 14.12.2011

Это неправда, SQLite 3 поддерживает несколько подключений, и вы можете оставить их оба открытыми. Просто обязательно используйте транзакцию в потоке обновления и закройте ее как можно скорее.

Прочитайте об этом в http://www.sqlite.org/lockingv3.html.

Если вы используете python, вы можете, например. установите параметр timeout при подключении к базе данных, что гарантирует, что поток чтения будет ждать до тайм-аута секунд, прежде чем сдаться. Поэтому важно сделать апдейтер максимально компактным, чтобы читатель не терял времени.

http://docs.python.org/library/sqlite3.html

Кроме того, я настоятельно рекомендую следующую книгу, если вы хотите узнать больше. Полное руководство по SQLite: http://www.apress.com/9781590596739

person Joe M.    schedule 14.12.2011