当前位置: 动力学知识库 > 问答 > 编程问答 >

database - In Android which causes SQLiteDatabaseLockedException exception to be thrown

问题描述:

I want to know what happens behind the scenes which causes this exception "SQLiteDatabaseLockedException" to be thrown with message "database is locked".

I am not asking for resolving this exception (because I already did it.)

I want to know how the things are working in background. I had gone through the source code of classes SQLiteOpenHelper and SQLiteDatabase.Both these classes are Thread-safe as the methods are synchronized (or using synchronized block).

I did not find any line which says "throw new SQLiteDatabaseLockedException("database is locked). I also read the classes which are refered in SQLiteDatabase like SQLiteConnection, SQLiteConnectionPool, but did'nt find anything useful. I read somewhere on the internet that SQLite maintains its internal locking. Is it means the native libraries of SQLite?

Please someone explains in depth what is happening behind the scenes.

Thanks.

网友答案:

I have faced your problem a few months ago and struggle against it a day or two...

Your problem is in the connections. You must not use different connections because each active connection locks the database when it uses it. If you want to execute parallel operations over the database, you can still use threads but take in mind that you must do the synchronization in your java code. You have to options for synchronization:

  • java locking mechanisms: synchronized and locks
  • SQL transactions

I advise you to use both. Use transactions everywhere you are performing DB operation (no matter if you are doing it in parallel or not). This way you will be safe from experiencing future problems with reading wrong/old/partial data. Use the java concurrent API when you are dealing with concurrent access to java objects that are related to the database (e.x: a counter that tracks the number of parallel java consumers of the database, the db helper instance, etc).

I have used the following code to manage the access to the database connection. I hope this snippet will help you solve your problems. Take in mind that this code snippet is taken from an existing project so it contains references to class name and methods that are not shown here but I hope the basic idea is clear.

/**
 * 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();
    }
}
分享给朋友:
您可能感兴趣的文章:
随机阅读: