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


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

Итак, у меня есть приложение, которое опубликовано в магазине, и с новой версией, которую я хотел выпустить, схема БД изменилась, поэтому я, естественно, должен был иметь миграции на месте, которые позаботились об обновлении его с версии 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$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)

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

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

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

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

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 года