2015-04-30 4 views
0

Я хочу знать, что происходит за кулисами, которые вызывают это исключение «SQLiteDatabaseLockedException», которое должно быть сброшено с сообщением «база данных заблокирована».В Android, вызывающем исключение SQLiteDatabaseLockedException

Я не прошу разрешения этого исключения (потому что я уже сделал это.) Я хочу знать, как все работает в фоновом режиме. Я прошел через исходный код классов SQLiteOpenHelper и SQLiteDatabase. Оба эти класса являются потокобезопасными, поскольку методы синхронизируются (или используют синхронизированный блок).

Я не нашел строки, в которой говорится: «Бросьте новое SQLiteDatabaseLockedException (« база данных заблокирована »). Я также читал классы, которые упоминаются в SQLiteDatabase, например SQLiteConnection, SQLiteConnectionPool, но не нашли ничего полезного. Я где-то читал в Интернете, что SQLite поддерживает свою внутреннюю блокировку. Это означает, что на родные библиотеки SQLite?

Пожалуйста, кто-то подробно объясняет, что происходит за кулисами. Спасибо.

+0

Как правило, такое исключение получено, когда вы пытаетесь открыть базу данных, пока она уже открыта. Самая лучшая практика говорит, что всегда закрывайте свой дБ, когда он больше не используется. – Ravi

+0

http://grepcode.com/file/repository.grepcode.com/java/ext/com.google.android/android/4.4_r1/android/database/sqlite/SQLiteDatabaseLockedException.java – Amsheer

+1

Отображаются номер строки и имя класса в logcat .. –

ответ

0

я столкнулся вашу проблему несколько месяцев назад, и борьба с ней через день или два ...

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

  • ява запирающие механизмы: synchronized и замки
  • SQL транзакции

Я советую вам использовать оба. Используйте транзакции везде, где вы выполняете операцию БД (независимо от того, выполняете ли вы это параллельно или нет). Таким образом, вы будете в безопасности от будущих проблем с чтением неправильных/старых/частичных данных. Используйте API-интерфейс java, когда вы имеете дело с одновременным доступом к объектам Java, связанным с базой данных (e.x: счетчик, который отслеживает количество параллельных java-пользователей базы данных, экземпляр-помощник db и т. Д.).

Я использовал следующий код для управления доступом к соединению с базой данных. Надеюсь, этот фрагмент поможет решить ваши проблемы. Имейте в виду, что этот фрагмент кода взят из существующего проекта, поэтому он содержит ссылки на имя и методы класса, которые здесь не показаны, но я надеюсь, что основная идея понятна.

/** 
* Defines the supported database types of access 
*/ 
public enum AccessType { 
    READABLE, WRITABLE; 
} 

protected static volatile SQLiteDatabase sDatabase; 
private static volatile int sCounter; 
private static final Object LOCK = new Object(); 

/** 
* Opens the database for access. 
* 
* @param accessType 
*   The type of access to be used. 
* @throws SQLException 
*    If something goes wrong. 
*/ 
public final void open(final AccessType accessType) throws SQLException { 
    synchronized (LOCK) { 
     sCounter++; 

     if (sDatabase != null && sDatabase.isOpen()) { 
      return; 
     } 

     switch (accessType) { 
     case READABLE: { 
      sDatabase = mDBHelper.getReadableDatabase(); 
      break; 
     } 
     case WRITABLE: { 
      sDatabase = mDBHelper.getWritableDatabase(); 
      break; 
     } 
     default: 
      throw new IllegalArgumentException("This AccessType is not supported!"); 
     } 
    } 
} 

/** 
* Closes the database connection. 
*/ 
public final void close() { 
    synchronized (LOCK) { 
     sCounter--; 

     if (sCounter == 0 && sDatabase != null && sDatabase.isOpen()) { 
      sDatabase.close(); 
     } 
    } 
} 

@Override 
public final void create(final T entry) { 
    sDatabase.beginTransaction(); 
    try { 
     doCreate(entry); 
     sDatabase.setTransactionSuccessful(); 
    } finally { 
     sDatabase.endTransaction(); 
    } 
} 
+0

Спасибо за ответ, но я не прошу разрешения. Потому что я уже решу это. Просто хочу узнать внутренние подробности о том, как блокировать работу SQLite в Android при доступе к нескольким потокам. – Naveen

+0

volatile не принадлежит – sstn

Смежные вопросы