我的sqlite数据库正在运行锁定,即使我已启用WAL
并且我在整个应用程序中使用了我的DbHelper的单例实例,如下所示:
public class DbHelper extends SQLiteOpenHelper {
private static final String mTAG = "DB_HELPER";
private static DatabaseHelper sInstance;
private static final String DATABASE_NAME = "database_name";
private static final int DATABASE_VERSION = 1;
public static synchronized DatabaseHelper getInstance(Context context) {
if (sInstance == null) {
sInstance = new DatabaseHelper(context.getApplicationContext());
}
return sInstance;
}
private DatabaseHelper(Context context) {
super(context, DATABASE_NAME, null, DATABASE_VERSION);
}
}
对于插入,我有以下功能:
public void insertToDb(String tableName, ContentValues contentValues) {
SQLiteDatabase sqLiteDatabase = this.getWritableDatabase();
sqLiteDatabase.enableWriteAheadLogging();
sqLiteDatabase.beginTransactionNonExclusive();
sqLiteDatabase.insert(tableName, null, contentValues);
sqLiteDatabase.setTransactionSuccessful();
sqLiteDatabase.endTransaction();
sqLiteDatabase.close();
}
知道为什么会这样吗?
更新
我有一个asynctask,问题源于抛出attempt to re-open an already-closed object
异常。接下来,我开始在我的logcat中得到以下错误:
#################################################################
Error Code : 5 (SQLITE_BUSY)
Caused By : The database file is locked.
(database is locked (code 5))
#################################################################
' Stack Trace: 'android.database.sqlite.SQLiteDatabaseLockedException: database is locked (code 5)
#################################################################
Error Code : 5 (SQLITE_BUSY)
Caused By : The database file is locked.
(database is locked (code 5))
#################################################################
at android.database.sqlite.SQLiteConnection.nativeExecute(Native Method)
at android.database.sqlite.SQLiteConnection.execute(SQLiteConnection.java:679)
at android.database.sqlite.SQLiteSession.beginTransactionUnchecked(SQLiteSession.java:319)
at android.database.sqlite.SQLiteSession.beginTransaction(SQLiteSession.java:298)
at android.database.sqlite.SQLiteDatabase.beginTransaction(SQLiteDatabase.java:510)
at android.database.sqlite.SQLiteDatabase.beginTransactionNonExclusive(SQLiteDatabase.java:445)
at com.ontheway.otw.entermarkets.helpers.database.OTWUserDb.updateOTWUserLocation(OTWUserDb.java:124)
at com.ontheway.otw.entermarkets.services.FusedLocationService.onLocationChanged(FusedLocationService.java:146)
at com.google.android.gms.internal.zzart$zzb$1.zza(Unknown Source)
at com.google.android.gms.internal.zzart$zzb$1.zzs(Unknown Source)
at com.google.android.gms.internal.zzaaz.zzb(Unknown Source)
at com.google.android.gms.internal.zzaaz$zza.handleMessage(Unknown Source)
at android.os.Handler.dispatchMessage(Handler.java:102)
at android.os.Looper.loop(Looper.java:148)
at android.app.ActivityThread.main(ActivityThread.java:7325)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:1230)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1120)
'
答案 0 :(得分:2)
SQLiteDatabase
(由SQLiteOpenHelper
包裹)是线程安全的(每个线程使用SQLiteConnectionPool
和SQLiteSession
)但你应该不关闭< / strong>它直到你完全完成数据库,对于大多数应用程序永远不会。这基本上就是链接文章所说的内容。
另一方面,您应确保交易始终结束,即使不成功,例如:
SQLiteDatabase sqLiteDatabase = this.getWritableDatabase();
sqLiteDatabase.enableWriteAheadLogging();
sqLiteDatabase.beginTransactionNonExclusive();
try {
sqLiteDatabase.insert(tableName, null, contentValues);
sqLiteDatabase.setTransactionSuccessful();
} finally {
sqLiteDatabase.endTransaction();
}
答案 1 :(得分:0)
一个数据库连接对象等于一个事务,因此多个线程必须使用多个数据库连接。
或者,您可以确保没有两个线程同时访问数据库。但是,将synchronized
放在getInstance()
上是不够的;您必须使用共享锁锁定所有数据库代码(例如,整个insertToDb()
函数)。