我有一个遗留应用程序正在使用Room,一旦执行第一个数据库查询就会崩溃,无论查询是什么。
java.lang.RuntimeException: Unable to start service com.someco.android.nettasks.PushQueueService@24ccdca6 with Intent { cmp=com.someco.android/.nettasks.PushQueueService }: android.database.sqlite.SQLiteException: Cannot execute this statement because it might modify the database but the connection is read-only.
at android.app.ActivityThread.handleServiceArgs(ActivityThread.java:3439)
at android.app.ActivityThread.access$2200(ActivityThread.java:181)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1572)
at android.os.Handler.dispatchMessage(Handler.java:102)
at android.os.Looper.loop(Looper.java:145)
at android.app.ActivityThread.main(ActivityThread.java:6117)
at java.lang.reflect.Method.invoke(Native Method)
at java.lang.reflect.Method.invoke(Method.java:372)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:1399)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1194)
Caused by: android.database.sqlite.SQLiteException: Cannot execute this statement because it might modify the database but the connection is read-only.
at io.requery.android.database.sqlite.SQLiteConnection.throwIfStatementForbidden(SQLiteConnection.java:1091)
at io.requery.android.database.sqlite.SQLiteConnection.executeForChangedRowCount(SQLiteConnection.java:755)
at io.requery.android.database.sqlite.SQLiteSession.executeForChangedRowCount(SQLiteSession.java:764)
at io.requery.android.database.sqlite.SQLiteStatement.executeUpdateDelete(SQLiteStatement.java:71)
at io.requery.android.database.sqlite.SQLiteDatabase.executeSql(SQLiteDatabase.java:1867)
at io.requery.android.database.sqlite.SQLiteDatabase.execSQL(SQLiteDatabase.java:1808)
at android.arch.persistence.room.RoomOpenHelper.createMasterTableIfNotExists(RoomOpenHelper.java:131)
at android.arch.persistence.room.RoomOpenHelper.checkIdentity(RoomOpenHelper.java:107)
at android.arch.persistence.room.RoomOpenHelper.onOpen(RoomOpenHelper.java:100)
at io.requery.android.database.sqlite.RequerySQLiteOpenHelperFactory$CallbackSQLiteOpenHelper.onOpen(RequerySQLiteOpenHelperFactory.java:67)
at io.requery.android.database.sqlite.SQLiteOpenHelper.getDatabaseLocked(SQLiteOpenHelper.java:283)
at io.requery.android.database.sqlite.SQLiteOpenHelper.getWritableDatabase(SQLiteOpenHelper.java:174)
at io.requery.android.database.sqlite.SQLiteOpenHelper.getWritableDatabase(SQLiteOpenHelper.java:44)
at com.someco.android.dmodel.OurDB.writableDb(OurDB.java:363)
at com.someco.android.nettasks.PushQueueService.startExecution(PushQueueService.java:202)
at com.someco.android.nettasks.PushQueueService.onStartCommand(PushQueueService.java:157)
at android.app.ActivityThread.handleServiceArgs(ActivityThread.java:3422)
at android.app.ActivityThread.access$2200(ActivityThread.java:181)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1572)
at android.os.Handler.dispatchMessage(Handler.java:102)
at android.os.Looper.loop(Looper.java:145)
at android.app.ActivityThread.main(ActivityThread.java:6117)
at java.lang.reflect.Method.invoke(Native Method)
at java.lang.reflect.Method.invoke(Method.java:372)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:1399)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1194)
根据我对调试器的调查,发生的事情是,在sqlite本身调用sqlite3_stmt_readonly()
方面存在某种竞争问题。这是导致崩溃的实际查询,来自RoomOpenHelper#createMastertableIfNotExists
:
CREATE TABLE IF NOT EXISTS room_master_table (id INTEGER PRIMARY KEY,identity_hash TEXT)
在RoomOpenHelper#onCreate
中,表格已成功创建。一个语句似乎被编译了两次,并检查了两次只读状态:
SQLiteProgram
的构造函数(通过SQLiteStatement
)SQLiteConnection#executeForChangedRowCount
所发生的情况是,为第一个获取的连接以更宽松的权限打开(6
,对我来说 - 1
是表示只读状态的位),并且它已正确评估不是只读的。这意味着请求第二个语句编译的连接使用只读标志(5
,对我而言)。发生崩溃是因为出于某种原因,查询被评估为不再是只读的。
我完全失去了这个。为什么会崩溃?相同的语句有时是只读的,而其他时候不是只读的吗?
答案 0 :(得分:1)
问题是房间TimeCreationOf(() => new ClassTwo(), c =>
{
c.SomeProperty = "x";
c.DoSomethingElse();
});
不支持预写日志。我删除了在应用中启用它的行:
1.0.0
版本db.getOpenHelper().setWriteAheadLoggingEnabled(true);
支持WAL。尝试新的alpha后,一切正常,所以更改日志指出了答案。我已经example project对该问题进行了简要的记录。