android - Room (266) 语句中止磁盘 I/O 错误
问题描述
在我的数据库中快速插入 X 条记录后,应用程序在某个点崩溃并出现以下堆栈跟踪:
2021-03-17 15:25:22.766 26711-26827/it.gabtamagnini.visualstock E/SQLiteLog: (266) statement aborts at 34: [SELECT * FROM corpo WHERE id_testata = ? ORDER BY timestamp ASC] disk I/O error
2021-03-17 15:25:22.766 26711-26827/it.gabtamagnini.visualstock E/SQLiteQuery: exception: disk I/O error (code 266); query: SELECT * FROM corpo WHERE id_testata = ? ORDER BY timestamp ASC
2021-03-17 15:25:22.790 26711-26711/it.gabtamagnini.visualstock E/AndroidRuntime: FATAL EXCEPTION: main
Process: it.gabtamagnini.visualstock, PID: 26711
android.database.sqlite.SQLiteDiskIOException: disk I/O error (code 266)
at android.database.sqlite.SQLiteConnection.nativeExecuteForCursorWindow(Native Method)
at android.database.sqlite.SQLiteConnection.executeForCursorWindow(SQLiteConnection.java:846)
at android.database.sqlite.SQLiteSession.executeForCursorWindow(SQLiteSession.java:836)
at android.database.sqlite.SQLiteQuery.fillWindow(SQLiteQuery.java:62)
at android.database.sqlite.SQLiteCursor.fillWindow(SQLiteCursor.java:143)
at android.database.sqlite.SQLiteCursor.getCount(SQLiteCursor.java:132)
at it.gabtamagnini.visualstock.database.CorpoDAO_Impl$14.call(CorpoDAO_Impl.java:393)
at it.gabtamagnini.visualstock.database.CorpoDAO_Impl$14.call(CorpoDAO_Impl.java:381)
at androidx.room.CoroutinesRoom$Companion$createFlow$1$1.invokeSuspend(CoroutinesRoom.kt:81)
at kotlin.coroutines.jvm.internal.BaseContinuationImpl.resumeWith(ContinuationImpl.kt:33)
at kotlinx.coroutines.DispatchedTask.run(DispatchedTask.kt:106)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1162)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:636)
at java.lang.Thread.run(Thread.java:764)
实际上我调用调用堆栈跟踪中的查询的DAO方法是在活动的onCreate的观察方法中,这里是代码:
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_lettura)
setSupportActionBar(findViewById(R.id.toolbar))
...
Transformations.switchMap(corpoViewModel.getIdTestata()) { id ->
corpoViewModel.getCorpo(id.toInt())
}.observe(this, { articoli ->
when (val count = articoli.count()) {
0 -> {
txtCountArticoli.text =
resources.getQuantityString(R.plurals.articoli, count, count)
if (bottomSheetBehavior.state == BottomSheetBehavior.STATE_EXPANDED) {
bottomSheetBehavior.state = BottomSheetBehavior.STATE_COLLAPSED
}
bottomSheet.setBackgroundColor(Color.parseColor("#C3858585"))
bottomSheetBehavior.isDraggable = false
}
1 -> {
bottomSheet.setBackgroundColor(Color.parseColor("#3D5AFE"))
bottomSheetBehavior.isDraggable = true
txtCountArticoli.text =
resources.getQuantityString(R.plurals.articoli, count, count)
}
else -> {
bottomSheet.setBackgroundColor(Color.parseColor("#3D5AFE"))
bottomSheetBehavior.isDraggable = true
txtCountArticoli.text =
resources.getQuantityString(R.plurals.articoli, count, count)
}
}
articoli.let { adapter.setData(articoli as MutableList<Corpo>) }
})
}
即使我在我的数据库中缓慢插入行并且我无法得到该错误的原因,我什至无法意识到如何修复它,我也遇到了同样的问题。
这是我的道:
@Query("SELECT * FROM corpo WHERE id_testata = :idTestata ORDER BY timestamp ASC")
fun getAll(idTestata: Int): Flow<List<Corpo>>
这是存储库:
@WorkerThread
fun getCorpo(idTestata: Int) : Flow<List<Corpo>>{
return corpoDAO.getAll(idTestata)
}
和视图模型:
fun getCorpo(idTestata: Int): LiveData<List<Corpo>>{
return repository.getCorpo(idTestata).asLiveData()
}
我的应用程序崩溃是什么问题,我该如何解决?
编辑:
我什至在该 Activity 中的 Fragment 中调用 .getCorpo
编辑 2(数据库实例):
@Database(entities = [Corpo::class, Prodotto::class, Barcode::class, Testata::class, Fornitori::class, PuntiVendita::class], version = 1, exportSchema = false)
abstract class PDTDatabase: RoomDatabase() {
abstract fun corpoDao(): CorpoDAO
abstract fun prodottiDao(): ProdottiDAO
abstract fun testataDao(): TestataDAO
companion object {
@Volatile
private var INSTANCE: PDTDatabase? = null
fun getDatabase(context: Context): PDTDatabase {
// 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,
PDTDatabase::class.java,
"visual_pdt"
)
.fallbackToDestructiveMigration()
.build()
INSTANCE = instance
// return instance
instance
}
}
}
}
然后我像这样在我的 Application() 中设置它:
class ArticoliApplication : Application() {
val database by lazy { PDTDatabase.getDatabase(this) }
val repository by lazy { CorpoRepository(database.corpoDao(), database.prodottiDao(), database.testataDao()) }
}
解决方案
我不确定答案,告诉我结果。
基于sqlite 文档和您的代码
(266) SQLITE_IOERR_READ
SQLITE_IOERR_READ 错误代码是 SQLITE_IOERR 的扩展错误代码,表示尝试从磁盘上的文件读取时 VFS 层中的 I/O 错误。此错误可能是由于硬件故障或文件系统在文件打开时卸载造成的。
我认为您的 db 对象实例化了两次。你需要仔细检查数据库实例化:更多关于双重检查
companion object {
@Volatile
private var INSTANCE: PDTDatabase? = null
fun getDatabase(context: Context): PDTDatabase {
// if the INSTANCE is not null, then return it,
// if it is, then create the database
return INSTANCE ?: synchronized(this) {
if (INSTANCE == null) {
val instance = Room.databaseBuilder(
context.applicationContext,
PDTDatabase::class.java,
"visual_pdt"
)
.fallbackToDestructiveMigration()
.build()
INSTANCE = instance
}
INSTANCE
}
}
}
推荐阅读
- sql - 如果表的视图仍在使用中,如何限制表被删除
- c# - 在 C# 中查找和获取具有特定属性的 XML 行
- activeweb - ActiveWeb:模拟注入服务
- keras - Keras-VGG16-places365 低准确率问题
- c# - 通过 HttpWebRequest 从页面转发隐藏字段
- html - 在 Opera/Chrome 浏览器中滚动时,粘性导航栏在某一点闪烁(渲染错误?)
- google-apps-script - 您可以将所有文本“存储”在谷歌文档中并在某人的编辑上重新写回吗?
- reactjs - React 组件道具样式
- javascript - Ajax 请求返回错误,而 .net 核心控制器返回 200 Ok
- angular - Angularfire 2对象插值不打印任何东西