Android 使用迁移升级房间数据库会导致数据库锁定

Android 使用迁移升级房间数据库会导致数据库锁定,android,sql,android-room,Android,Sql,Android Room,我将回答我自己的问题,这是问题描述。 所以我有一个应用程序发布在商店里,随着我想要发布的新版本的出现,DB模式发生了变化,所以我自然要进行迁移,将其从版本3升级到最新的版本5。这包括提供从3到4以及从4到5的迁移。或者一次从3到5 这就是我所做的,我提供了这些迁移,并将它们提供给Room databaseBuilder(),一切就绪,以模拟应用程序升级的场景(安装应用商店版本,运行它,登录,创建数据库,生成生产APK,并通过终端将其安装到设备上,运行) 这样做总是会产生以下异常: 05-19 0

我将回答我自己的问题,这是问题描述。

所以我有一个应用程序发布在商店里,随着我想要发布的新版本的出现,DB模式发生了变化,所以我自然要进行迁移,将其从版本3升级到最新的版本5。这包括提供从3到4以及从4到5的迁移。或者一次从3到5

这就是我所做的,我提供了这些迁移,并将它们提供给Room databaseBuilder(),一切就绪,以模拟应用程序升级的场景(安装应用商店版本,运行它,登录,创建数据库,生成生产APK,并通过终端将其安装到设备上,运行)

这样做总是会产生以下异常:

05-19 02:38:00.363 6472-6522/co.myapp.app E/ROOM: Invalidation tracker is initialized twice :/.
05-19 02:38:00.378 6472-6549/co.myapp.app E/ROOM: Cannot run invalidation tracker. Is the db closed?
java.lang.IllegalStateException: The database '/data/user/0/co.myapp.app/databases/my_db' is not open.
at android.database.sqlite.SQLiteDatabase.throwIfNotOpenLocked(SQLiteDatabase.java:2765)
at android.database.sqlite.SQLiteDatabase.createSession(SQLiteDatabase.java:490)
at android.database.sqlite.SQLiteDatabase$1.initialValue(SQLiteDatabase.java:88)
at android.database.sqlite.SQLiteDatabase$1.initialValue(SQLiteDatabase.java:87)
at java.lang.ThreadLocal.setInitialValue(ThreadLocal.java:160)
at java.lang.ThreadLocal.get(ThreadLocal.java:150)
at android.database.sqlite.SQLiteDatabase.getThreadSession(SQLiteDatabase.java:484)
at android.database.sqlite.SQLiteProgram.getSession(SQLiteProgram.java:107)
at android.database.sqlite.SQLiteStatement.executeUpdateDelete(SQLiteStatement.java:64)
at android.arch.persistence.db.framework.FrameworkSQLiteStatement.executeUpdateDelete(FrameworkSQLiteStatement.java:45)
at android.arch.persistence.room.InvalidationTracker$1.run(InvalidationTracker.java:321)
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:762)
迁移正在成功运行,并且正在按照我写的那样创建表,但是在Room升级您的DB版本并迁移之后,每次DB访问操作中都会出现异常。升级后的每次读写操作都会导致此异常

  • 首先,我认为这是迁移的问题,但迁移是正确的(检查了SQL,Room没有抱怨任何类似的问题,通常它做得很好,并告诉您哪些不匹配)
  • 然后我认为问题在于一次向它提供2次迁移(我以前做过,没有问题),但我删除了4到5次迁移,并将其放在3到5次迁移中,以便一次性运行整个过程。没用
  • 然后我想,我可以放弃,说“好吧,就做回退到Destructive Migration(),让Room重新创建一切,导致所有用户注销并丢失数据,这是我不想做的,但我只是想看看这会导致什么结果。所以我没有为迁移提供信息,只是忽略了它们。例外情况仍然存在
这个异常是悄无声息地发生的,它没有使应用程序崩溃,也没有引用我代码中的任何地方,它只是发生在Logcat中,并且在它发生一次时阻止了任何类型的DB访问。无论您是否输入了迁移代码,或者您是否希望退回到破坏性迁移,Room检测到您升级了DB的那一刻就会将其锁定,并阻止对其进行任何访问

我已经在三星S6、Nexus 5、OnePlus、摩托罗拉Moto C和谷歌Pixel上进行了测试,到处都是相同的问题。

我在浏览这个页面时,发现了一条漂亮的线:

我使用的是Room版本1.1.0,当然,因为它应该是稳定的,我们需要稳定、可靠的软件,当然我们可以依赖谷歌

将版本升级到1.1.1-rc1,我可以有把握地说,这个源于谷歌自己代码的荒谬错误现在已经消失了,我已经在原始问题中提到的所有设备上重新测试了相同的场景


发生异常时要小心,不要提及您的代码。这是房间1.1.0中的一个bug,请确认您是否见过它,这是我在网上看到的唯一一个提及它的地方

您好,我也遇到了同样的问题,但它没有阻止对数据库的访问。我已经降级了Kotlin和Room的版本,正如我对这个问题的第二个答案的评论所示。我也有同样的问题。更新到稳定的1.1.1修复了它。谢谢你,伙计!2.2.5号房间也有同样的问题
def room_version = "1.1.0" // or, for latest rc, use "1.1.1-rc1"