【问题标题】:Sqlite database locking with (WAL) write-ahead logging enabled启用 (WAL) 预写日志记录的 Sqlite 数据库锁定
【发布时间】:2017-01-09 05:04:06
【问题描述】:

即使我启用了WAL 并且我在整个应用程序中使用了我的 DbHelper 的单例实例,我的 sqlite 数据库也遇到了锁,​​如下所示:

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();
}

知道为什么会发生这种情况吗?

更新: 我有一个异步任务,问题源于抛出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)
'

【问题讨论】:

  • 到底哪里失败了?错误信息是什么?
  • 我在上面添加了错误详情。
  • 是什么让您认为可以在多个线程中使用单个数据库对象?
  • 这就是单例的全部目的,不是吗?还是每个线程和后台服务都在启动自己的实例?
  • 你是在问你在做什么或者你应该做什么?

标签: android sqlite


【解决方案1】:

SQLiteDatabase(由SQLiteOpenHelper 包裹)是线程安全的(它对每个线程使用SQLiteConnectionPoolSQLiteSession),但您应该不要关闭它,直到您完全关闭它完成数据库,这对于大多数应用程序来说是永远不会的。这基本上就是链接文章所说的。

另一方面,您应该确保事务始终结束,即使不成功,例如:

SQLiteDatabase sqLiteDatabase = this.getWritableDatabase();
sqLiteDatabase.enableWriteAheadLogging();
sqLiteDatabase.beginTransactionNonExclusive();
try {
    sqLiteDatabase.insert(tableName, null, contentValues);
    sqLiteDatabase.setTransactionSuccessful();
} finally {
    sqLiteDatabase.endTransaction();
}

【讨论】:

    【解决方案2】:

    一个DB连接对象等于一个事务,所以多个线程必须使用多个DB连接。

    或者,您可以确保没有两个线程同时访问数据库。但是,将synchronized 放在getInstance() 上是不够的;您必须使用共享锁锁定所有数据库代码(例如,整个 insertToDb() 函数)。

    【讨论】:

      猜你喜欢
      • 2013-07-03
      • 1970-01-01
      • 2016-08-26
      • 1970-01-01
      • 1970-01-01
      • 2010-12-27
      • 1970-01-01
      • 2021-06-27
      • 2013-11-14
      相关资源
      最近更新 更多