Обновление БД комнаты с миграциями вызывает блокировку БД

Я собираюсь ответить на мой собственный вопрос, это описание проблемы.

Итак, у меня есть приложение, опубликованное в магазине, и с новой версией, которую я хотел выпустить, схема БД изменилась, поэтому мне, естественно, пришлось выполнить миграцию, которая позаботилась об обновлении ее с версии 3 до последней версии 5. Это включает в себя обеспечение миграции от 3 до 4 и от 4 до 5. Или от 3 до 5 за один раз.

Так вот что я сделал, я при условии, что эти миграции и кормили их в комнату 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)

миграции выполнялись успешно, и таблицы создавались так, как я написал, но это исключение продолжал появляться на каждой операции доступа к БД сразу после обновления номера вашей версии БД и миграции. Каждое чтение или запись после обновления вызовет это исключение

  • сначала я думал, что это проблема с миграциями, но миграции были правильными (SQL был проверен, и номер не жаловался ни на что подобное, обычно он делает это очень хорошо и говорит вам, что не соответствует).
  • тогда я думал, что проблема была с кормлением его 2 миграции сразу (что я делал раньше, и не было никаких проблем), но я удалил миграцию 4 до 5 и поместил ее в 3 до 5, чтобы запустить все это за один раз. Бесполезно.
  • тогда я подумал, что хорошо, я всегда могу сдаться и сказать ок, просто сделай fallbackToDestructiveMigration() и пусть номер воссоздает все, в результате чего все пользователи выходят из системы и теряют свои данные, что я не хотел делать, но я просто хотел посмотреть, где это будет вести. Поэтому я не кормил переселенцев и просто игнорировал их. Исключение все же произошло.

это исключение происходило тихо, оно не разбивало приложение, и оно не ссылалось ни на что в моем коде, это просто произошло в Logcat и предотвратило какой-либо доступ к БД в тот момент, когда это произошло даже один раз. Независимо от того, ввели ли вы миграционный код или нет, Хотите ли вы вернуться к деструктивной миграции или нет, момент Room обнаруживает, что вы обновили свою БД он блокирует его и просто предотвращает любой доступ к нему.

Я тестировал это на Samsung S6, Nexus 5, OnePlus, Motorola Moto C и Google Pixel, точно такая же проблема везде.

1 ответов


Я просматривал эту страницу при добавлении компонентов архитектуры в приложение и я наткнулся на эту прекрасную строку:

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

я использовал версию номер 1.1.0, естественно, потому что он должен быть стабильным, и мы хотим стабильное, твердое программное обеспечение, на которое мы можем положиться от Google, конечно.

поднял версию до 1.1.1-rc1 и я могу смело сказать, что эта бессмысленная ошибка, которая проистекает из собственного кода Google теперь ушел, я перепробовал тот же сценарий на всех устройствах, которые я упомянул в исходном вопросе.

будьте осторожны, когда происходят исключения и не упоминается ваш код. Это ошибка в номере 1.1.0, Пожалуйста, подтвердите, если вы видели его, только упоминание о нем в интернете, что я видел это здесь с 2017 года