安卓数据库被锁定。

5

我在生产环境中遇到了"android.database.sqlite.SQLiteDatabaseLockedException"异常。在错误分析期间发生了异常。我的项目数据库是room。该项目中没有使用多进程。数据库room已经封装了事务操作。我不知道为什么数据库被锁定了。希望能得到您的帮助,谢谢!

this is exception

Process Name: 'com.geek.jk.weather'
Thread Name: 'kotlinx.coroutines.scheduling.CoroutineScheduler$Worker#DefaultDispatcher-worker-2'
Back traces starts.
android.database.sqlite.SQLiteDatabaseLockedException: database is locked (code 5)
    at android.database.sqlite.SQLiteConnection.nativeExecute(Native Method)
    at android.database.sqlite.SQLiteConnection.execute(SQLiteConnection.java:553)
    at android.database.sqlite.SQLiteSession.beginTransactionUnchecked(SQLiteSession.java:323)
    at android.database.sqlite.SQLiteSession.beginTransaction(SQLiteSession.java:298)
    at android.database.sqlite.SQLiteDatabase.beginTransaction(SQLiteDatabase.java:505)
    at android.database.sqlite.SQLiteDatabase.beginTransaction(SQLiteDatabase.java:416)
    at androidx.sqlite.db.framework.FrameworkSQLiteDatabase.beginTransaction(FrameworkSQLiteDatabase.java:1)
    at androidx.room.RoomDatabase.beginTransaction(RoomDatabase.java:4)
    at com.xiaoniu.unitionadbase.collie.dao.EventTrackDao_Impl$3.call(EventTrackDao_Impl.java:2)
    at com.xiaoniu.unitionadbase.collie.dao.EventTrackDao_Impl$3.call(EventTrackDao_Impl.java:1)
    at androidx.room.CoroutinesRoom$Companion$execute$2.invokeSuspend(CoroutinesRoom.kt:2)
    at Rza.resumeWith(ContinuationImpl.kt:3)
    at WIa.run(DispatchedTask.kt:18)
    at androidx.room.TransactionExecutor$1.run(TransactionExecutor.java:1)
    at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1113)
    at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:588)
    at java.lang.Thread.run(Thread.java:818)
    Back traces ends.

数据库

@Database(entities = [CommonTrack::class, EventTrack::class], version = 1)
abstract class TrackDatabase : RoomDatabase() {
abstract fun CommonTrackDao(): CommonTrackDao
abstract fun EventTrackDao(): EventTrackDao

companion object {

    private var instance: TrackDatabase? = null


    fun getInstance(context: Context): TrackDatabase {
        return instance ?: instance ?: buildDatabase(context).also { instance = it }
        
    }

    fun buildDatabase(context: Context): TrackDatabase {
        if (instance == null) {
            instance = Room.databaseBuilder(
                    context.applicationContext,
                    TrackDatabase::class.java,
                    "event_track.db"
            ).allowMainThreadQueries().build()

        }
        return instance as TrackDatabase
    }
}

数据库使用

@Dao
abstract class EventTrackDao {

@Query("select * from event_table limit 50 ")
abstract suspend fun getEventTack():List<EventTrack>

@Query("select count(*) from event_table")
abstract suspend fun getEventCounts():Int

@Insert(onConflict = OnConflictStrategy.REPLACE)
abstract suspend fun insertEventTrack(events: List<EventTrack>):List<Long>

@Insert(onConflict = OnConflictStrategy.REPLACE)
abstract suspend fun insertEventTrack(event:EventTrack):Long


@Delete
abstract suspend  fun removeEvent(events: List<EventTrack>)

}

val call=  TrackDatabase.getInstance(context).EventTrackDao().insertEventTrack(eventslist)

GlobalScope.launch(Dispatchers.IO) {
                        runCatching {
                            val 
                            list=TrackDatabase.getInstance(context).EventTrackDao().getEventCounts()

                        }.onFailure {t ->
                            
                       }
                    }

EventTrackDao_Impl

public final class EventTrackDao_Impl extends EventTrackDao {
private final RoomDatabase __db;

private final EntityInsertionAdapter<EventTrack> __insertionAdapterOfEventTrack;

private final EntityDeletionOrUpdateAdapter<EventTrack> __deletionAdapterOfEventTrack;

public EventTrackDao_Impl(RoomDatabase __db) {
  this.__db = __db;
  this.__insertionAdapterOfEventTrack = new EntityInsertionAdapter<EventTrack>(__db) {
  @Override
  public String createQuery() {
    return "INSERT OR REPLACE INTO `event_table` (`event_param`,`ts`) VALUES (?,?)";
  }

  @Override
  public void bind(SupportSQLiteStatement stmt, EventTrack value) {
    if (value.getParam() == null) {
      stmt.bindNull(1);
    } else {
      stmt.bindString(1, value.getParam());
    }
    stmt.bindLong(2, value.getTs());
  }
};
this.__deletionAdapterOfEventTrack = new EntityDeletionOrUpdateAdapter<EventTrack>(__db) {
  @Override
  public String createQuery() {
    return "DELETE FROM `event_table` WHERE `event_param` = ?";
  }

  @Override
  public void bind(SupportSQLiteStatement stmt, EventTrack value) {
    if (value.getParam() == null) {
      stmt.bindNull(1);
    } else {
      stmt.bindString(1, value.getParam());
    }
  }
};

} }

2个回答

2
你的数据库类仍允许多线程修改,因为锁定了数据库。使用 volatilesynchronized 修改类数据库如下:
@Database(entities = arrayOf(Word::class), version = 1, exportSchema = false)
public abstract class WordRoomDatabase : RoomDatabase() {

   abstract fun wordDao(): WordDao

   companion object {
        // Singleton prevents multiple instances of database opening at the
        // same time. 
        @Volatile
        private var INSTANCE: WordRoomDatabase? = null

        fun getDatabase(context: Context): WordRoomDatabase {
            // if the INSTANCE is not null, then return it,
            // if it is, then create the database
            return INSTANCE ?: synchronized(this) {
                val instance = Room.databaseBuilder(
                        context.applicationContext,
                        WordRoomDatabase::class.java, 
                        "word_database"
                    ).build()
                INSTANCE = instance
                // return instance
                instance
            }
        }
   }
}

您必须在具有IO上下文的协程范围内调用插入操作。


谢谢,修改类数据库添加volatile和synchronized,问题仍然存在。 - hanchen ke
@hanchenke 我更新了答案。你调用insert的原因不在协程范围内。 - Tungken
我的项目在协程范围内调用了insert函数。这里只是展示insert代码。 - hanchen ke

0
我通过移除同步块并在构建器中添加以下代码 .enableMultiInstanceInvalidation() 来解决了这个问题。
应该变成 Room.databaseBuilder(context.applicationContext, WordRoomDatabase::class.java, "word_database").enableMultiInstanceInvalidation().build()

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接