使用迁移升级Room DB会导致数据库锁定

时间:2020-11-29 23:12:40

I am going to answer my own question, this is the problem description.

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

So I have an app that's published on the Store, and with the new version that I wanted to release, the DB schema had changed so I naturally had to have migrations in place that took care of upgrading it from version 3 to the most recent version 5. This includes providing migrations from 3 to 4 and from 4 to 5. Or from 3 to 5 in one go.

所以我有一个在商店发布的应用程序,并且我想要发布的新版本,数据库架构已经改变,所以我自然不得不进行迁移,负责将其从版本3升级到最新版本这包括提供3到4和4到5的迁移,或者一次性从3到5。

So that's what I did, I provided those migrations and fed them to the Room databaseBuilder() and everything was in place to simulate the scenario where an upgrade of the app is happening (install Store version, run it, log in, DB created, produce production APK and install it on device through terminal, run)

这就是我所做的,我提供了这些迁移并将它们提供给Room databaseBuilder(),并且所有内容都用于模拟应用程序升级发生的场景(安装Store版本,运行它,登录,创建DB,生产生产APK并通过终端安装在设备上,运行)

Doing this was always producing the following exception:

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

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)

The migrations were running successfully and the tables were being created as I had written, but that exception kept appearing on every single DB access operation right after Room upgrades your DB version and migrates. Every read or write after the upgrade happens will cause this exception

迁移成功运行并且正在按照我的编写创建表,但是在Room升级数据库版本并迁移之后,每个数据库访问操作都会出现异常。升级后的每次读取或写入都会导致此异常

  • First I thought that it was a problem with the migrations but the migrations were correct (the SQL was checked and Room didn't complain about anything of the sort, usually it does so very well and tells you what didn't match).
  • 首先我认为这是迁移的一个问题,但迁移是正确的(SQL已被检查,Room没有抱怨任何类型的东西,通常它做得很好,并告诉你什么不匹配)。

  • Then I thought the problem was with feeding it 2 migrations at once (which I'd done before, and there was no problem) but I removed the 4 to 5 migration and placed it in the 3 to 5 one to run the whole thing in one go. No use.
  • 然后我认为问题在于同时为它提供2次迁移(我以前做过,并且没有问题)但我删除了4到5次迁移并将其放在3到5之间以运行整个事情一个人去。没用

  • Then I thought well, I could always give up and say ok, just do fallbackToDestructiveMigration() and let Room recreate everything, causing all users to get logged out and have their data lost, something I didn't want to do but I just wanted to see where this will lead. So I didn't feed the migrations and just ignored them. The exception still happened.
  • 然后我想好了,我总是可以放弃并说好,只需做fallbackToDestructiveMigration()并让Room重新创建所有内容,导致所有用户退出并丢失数据,这是我不想做但我只是想要的看看这会导致什么。所以我没有提供迁移,只是忽略了它们。例外仍然发生。

This exception was happening silently, it wasn't crashing the app, nor was it referring to anywhere in my code, it just happened in Logcat and prevented any sort of DB access the moment it occurred even one time. Regardless if you've fed migration code or not, or whether you want to fall back to destructive migration or not, the moment Room detects that you've upgraded your DB it locks it down and just prevents any access to it whatsoever.

这个异常是静默发生的,它没有崩溃应用程序,也没有引用我的代码中的任何地方,它只是发生在Logcat中,并且在它发生甚至一次时阻止了任何类型的DB访问。无论您是否已经提供了迁移代码,或者您是否想要回退到破坏性迁移,Room会检测到您已升级数据库时将其锁定并且只是阻止对其进行任何访问。

I've tested this on Samsung S6, Nexus 5, OnePlus, Motorola Moto C and Google Pixel, exact same issue everywhere.

我已经在三星S6,Nexus 5,OnePlus,摩托罗拉Moto C和Google Pixel上测试了这一点,到处都是完全相同的问题。

1 个解决方案

#1


14  

I was browsing this page on adding Architecture Components to your app and I came across this beautiful line:

我正在浏览此页面,在您的应用中添加架构组件,我遇到了这条美丽的线路:

def room_version = "1.1.0" // or, for latest rc, use "1.1.1-rc1"

I was using Room version 1.1.0, naturally, because it should be stable and we want stable, solid software that we can rely on from Google, of course.

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

Bumped up the version to 1.1.1-rc1 and I can safely say that this nonsensical error that stems from Google's own code is now gone, I've retested the same scenario on all the devices I mentioned in the original question.

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

Be careful when exceptions occur and no mention of your code is included. This is a bug in Room 1.1.0, please confirm if you have seen it, the only other mention of it online that I've seen is this one here from 2017

发生异常时要小心,不要提及代码。这是房间1.1.0中的一个错误,请确认你是否已经看过它,我在网上看到的唯一一个提到它的是2017年的这个

#1


14  

I was browsing this page on adding Architecture Components to your app and I came across this beautiful line:

我正在浏览此页面,在您的应用中添加架构组件,我遇到了这条美丽的线路:

def room_version = "1.1.0" // or, for latest rc, use "1.1.1-rc1"

I was using Room version 1.1.0, naturally, because it should be stable and we want stable, solid software that we can rely on from Google, of course.

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

Bumped up the version to 1.1.1-rc1 and I can safely say that this nonsensical error that stems from Google's own code is now gone, I've retested the same scenario on all the devices I mentioned in the original question.

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

Be careful when exceptions occur and no mention of your code is included. This is a bug in Room 1.1.0, please confirm if you have seen it, the only other mention of it online that I've seen is this one here from 2017

发生异常时要小心,不要提及代码。这是房间1.1.0中的一个错误,请确认你是否已经看过它,我在网上看到的唯一一个提到它的是2017年的这个