使用迁移升级 Room DB 会导致数据库锁定
Upgrading Room DB with migrations causes DB lock
我来回答我自己的问题,这是问题描述。
所以我有一个在应用商店发布的应用程序,随着我想发布的新版本的发布,数据库架构发生了变化,所以我自然必须进行迁移,以便从版本 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.initialValue(SQLiteDatabase.java:88)
at android.database.sqlite.SQLiteDatabase.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.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 升级您的数据库版本和迁移。升级后每次读取或写入都会导致此异常
- 首先我认为这是迁移的问题,但迁移是正确的(检查了 SQL 并且 Room 没有抱怨任何类似的事情,通常它做得很好并且告诉你什么不匹配)。
- 然后我认为问题是一次向它提供 2 个迁移(我以前做过,没有问题)但是我删除了 4 到 5 个迁移并将它放在 3 到 5 个迁移中运行 一气呵成。没用。
- 然后我想好,我总是可以放弃并说好的,只需执行 fallbackToDestructiveMigration() 并让 Room 重新创建所有内容,导致所有用户注销并拥有他们的数据丢失,这是我不想做的事情,但我只是想看看这会导致什么结果。所以我没有提供迁移,只是忽略了它们。异常还是发生了。
这个异常悄无声息地发生,它没有使应用程序崩溃,也没有引用我代码中的任何地方,它只是发生在 Logcat 中,甚至在它发生的那一刻就阻止了任何类型的数据库访问一度。无论您是否提供了迁移代码,或者您是否想回退到破坏性迁移,当 Room 检测到您已经升级了您的数据库时,它会锁定它并阻止任何对其的访问。
我已经在三星 S6、Nexus 5、OnePlus、摩托罗拉 Moto C 和 Google Pixel 上测试过这个问题,到处都是同样的问题。
我正在浏览此页面 on adding Architecture Components to your app,我看到了这条漂亮的线:
def room_version = "1.1.0" // or, for latest rc, use "1.1.1-rc1"
我使用的是 Room 版本 1.1.0,当然,因为它应该是稳定的,我们想要稳定、可靠的软件,我们可以依赖 Google,当然可以。
将版本升级到 1.1.1-rc1 我可以肯定地说,这个源于 Google 自己的代码的荒谬错误现在已经消失了,我已经在原始问题中提到的所有设备上重新测试了相同的场景。
当出现异常并且没有提及您的代码时要小心。这是Room 1.1.0的一个bug,请确认你是否看到了,这是我在网上看到的唯一其他提及
我来回答我自己的问题,这是问题描述。
所以我有一个在应用商店发布的应用程序,随着我想发布的新版本的发布,数据库架构发生了变化,所以我自然必须进行迁移,以便从版本 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.initialValue(SQLiteDatabase.java:88)
at android.database.sqlite.SQLiteDatabase.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.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 升级您的数据库版本和迁移。升级后每次读取或写入都会导致此异常
- 首先我认为这是迁移的问题,但迁移是正确的(检查了 SQL 并且 Room 没有抱怨任何类似的事情,通常它做得很好并且告诉你什么不匹配)。
- 然后我认为问题是一次向它提供 2 个迁移(我以前做过,没有问题)但是我删除了 4 到 5 个迁移并将它放在 3 到 5 个迁移中运行 一气呵成。没用。
- 然后我想好,我总是可以放弃并说好的,只需执行 fallbackToDestructiveMigration() 并让 Room 重新创建所有内容,导致所有用户注销并拥有他们的数据丢失,这是我不想做的事情,但我只是想看看这会导致什么结果。所以我没有提供迁移,只是忽略了它们。异常还是发生了。
这个异常悄无声息地发生,它没有使应用程序崩溃,也没有引用我代码中的任何地方,它只是发生在 Logcat 中,甚至在它发生的那一刻就阻止了任何类型的数据库访问一度。无论您是否提供了迁移代码,或者您是否想回退到破坏性迁移,当 Room 检测到您已经升级了您的数据库时,它会锁定它并阻止任何对其的访问。
我已经在三星 S6、Nexus 5、OnePlus、摩托罗拉 Moto C 和 Google Pixel 上测试过这个问题,到处都是同样的问题。
我正在浏览此页面 on adding Architecture Components to your app,我看到了这条漂亮的线:
def room_version = "1.1.0" // or, for latest rc, use "1.1.1-rc1"
我使用的是 Room 版本 1.1.0,当然,因为它应该是稳定的,我们想要稳定、可靠的软件,我们可以依赖 Google,当然可以。
将版本升级到 1.1.1-rc1 我可以肯定地说,这个源于 Google 自己的代码的荒谬错误现在已经消失了,我已经在原始问题中提到的所有设备上重新测试了相同的场景。
当出现异常并且没有提及您的代码时要小心。这是Room 1.1.0的一个bug,请确认你是否看到了,这是我在网上看到的唯一其他提及