Room数据库随机出现SQLiteDatabaseLockedException崩溃求助
在Firebase Crashlytics中收到随机触发的崩溃日志,开发阶段从未捕获到该异常:
Fatal Exception: android.database.sqlite.SQLiteDatabaseLockedException: database is locked (Sqlite code 5), (OS error - 11:Try again) at android.database.sqlite.SQLiteConnection.nativeExecute(SQLiteConnection.java) at android.database.sqlite.SQLiteConnection.execute(SQLiteConnection.java:591) at android.database.sqlite.SQLiteSession.beginTransactionUnchecked(SQLiteSession.java:332) at android.database.sqlite.SQLiteSession.beginTransaction(SQLiteSession.java:311) at android.database.sqlite.SQLiteDatabase.beginTransaction(SQLiteDatabase.java:532) at android.database.sqlite.SQLiteDatabase.beginTransactionNonExclusive(SQLiteDatabase.java:467) at androidx.sqlite.db.framework.FrameworkSQLiteDatabase.beginTransactionNonExclusive(FrameworkSQLiteDatabase.java:78) at androidx.room.RoomDatabase.internalBeginTransaction(RoomDatabase.java:570) at androidx.room.RoomDatabase.beginTransaction(RoomDatabase.java:555) at androidx.work.impl.utils.StopWorkRunnable.run(StopWorkRunnable.java:56) at androidx.work.impl.utils.SerialExecutor$Task.run(SerialExecutor.java:91) at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1133) at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:607) at java.lang.Thread.run(Thread.java:776)
使用Room作为数据库,已尝试更新Room版本但问题未解决,请问是否可自行修复该问题?是否需要添加数据库相关配置参数?
解决方案
这个崩溃是WorkManager执行StopWorkRunnable时尝试开启Room事务,遭遇SQLite数据库锁定导致的,可通过以下方式修复:
保证Room操作的线程安全:
Room要求数据库操作不在主线程执行,但多线程(包括WorkManager后台线程)同时发起写操作仍会触发锁定。确保所有Room操作通过@Dao的suspend方法配合协程执行,避免手动开启事务后未及时提交/回滚,防止数据库连接长期被占用。配置SQLite超时重试与线程池:
在构建RoomDatabase时,设置SQLite的busy_timeout参数让数据库遇到锁定时自动重试,同时可指定单线程查询池避免并发冲突:Room.databaseBuilder(context, YourDatabase::class.java, "your_db_name") .setQueryExecutor(Executors.newSingleThreadExecutor()) .addCallback(object : RoomDatabase.Callback() { override fun onCreate(db: SupportSQLiteDatabase) { super.onCreate(db) // 设置5秒超时,期间自动重试锁定操作 db.execSQL("PRAGMA busy_timeout = 5000;") } }) .build()优化WorkManager任务的数据库操作:
检查Worker实现中是否存在未完成的事务或长时间占用数据库的操作。确保Worker内的数据库操作尽量简短,执行完成后及时释放连接;若需处理大量数据,拆分任务避免长时间持有锁。确认WAL模式启用:
Room默认启用WAL(Write-Ahead Logging)模式,该模式能提升并发性能、减少写操作锁定时间。可显式配置确保启用:Room.databaseBuilder(context, YourDatabase::class.java, "your_db_name") .setJournalMode(RoomDatabase.JournalMode.WAL) .build()避免跨进程访问数据库:
若App存在多进程,确保仅单个进程访问Room数据库,或通过ContentProvider封装数据库操作,防止多进程同时写导致锁定。
内容的提问来源于stack exchange,提问作者Verona1024

