我想知道幕后会发生什么导致此异常“SQLiteDatabaseLockedException”会抛出消息“数据库被锁定”。
我不是要求解决这个异常(因为我已经做过了。) 我想知道事情是如何在后台运作的。我已经浏览了SQLiteOpenHelper和SQLiteDatabase类的源代码。这些类在方法同步(或使用synchronized块)时是线程安全的。
我没有找到任何说“抛出新SQLiteDatabaseLockedException(”数据库被锁定)的行。我还阅读了SQLiteDatabase中提到的类,如SQLiteConnection,SQLiteConnectionPool,但没有找到任何有用的东西。我在互联网上的某处读到SQLite保持其内部锁定。它是否意味着SQLite的本地库?
请有人深入解释幕后发生的事情。 感谢。
答案 0 :(得分:0)
几个月前我遇到了你的问题并且在一两天内与它斗争......
您的问题在于连接。您不能使用不同的连接,因为每个活动连接在使用它时都会锁定数据库。如果要对数据库执行并行操作,仍可以使用线程,但请记住必须在java代码中执行同步。您必须选择同步:
synchronized
和锁我建议你两者兼用。在执行数据库操作的任何地方使用事务(无论您是否并行执行)。通过这种方式,您可以安全地避免阅读错误/旧/部分数据的未来问题。在处理与数据库相关的java对象的并发访问时使用java并发API(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();
}
}