Реализация миграции данных при обновлении мобильного приложения

Реализация миграции данных при обновлении мобильного приложения При обновлении мобильного приложения модель данных меняется не реже интерфейса. Клиенты приходят с типовой болью: после изменения схемы БД старые данные перестают корректно обрабатываться новой версией. Например, поле `amount` хранил

Разработка и поддержка любых видов мобильных приложений:

Информационные и развлекательные мобильные приложения
Новостные приложения, игры, справочники, онлайн-каталоги, погодные, фитнес и здоровье, туристические, образовательные, социальные сети и мессенджеры, квиз, блоги и подкасты, форумы, агрегаторы
Мобильные приложения электронной коммерции
Интернет-магазины, B2B-приложения, маркетплейсы, онлайн-обменники, кэшбэк-сервисы, биржи, дропшиппинг-платформы, программы лояльности, доставка еды и товаров, платежные системы
Мобильные приложения для управления бизнес-процессами
CRM-системы, ERP-системы, управление проектами, инструменты для команды продаж, учет финансов, управление производством, логистика и доставка, управление персоналом, системы мониторинга данных
Мобильные приложения электронных услуг
Доски объявлений, онлайн-школы, онлайн-кинотеатры, платформы предоставления электронных услуг, платформы кешбека, видеохостинги, тематические порталы, платформы онлайн-бронирования и записи, платформы онлайн-торговли

Это лишь некоторые из типы мобильных приложений, с которыми мы работаем, и каждый из них может иметь свои специфические особенности и функциональность, а также быть адаптированным под конкретные потребности и цели клиента.

Услуги, которые мы предлагаем
Показано 1 из 1Все 1734 услуг
Реализация миграции данных при обновлении мобильного приложения
Средний
~3-5 дней

Наши компетенции:

Часто задаваемые вопросы

Последние работы

  • Разработка мобильного приложения для компании FEEDME
    Разработка мобильного приложения для компании FEEDME
    941
  • Разработка мобильного приложения для компании XOOMER
    Разработка мобильного приложения для компании XOOMER
    813
  • Разработка мобильного приложения для компании RHL
    Разработка мобильного приложения для компании RHL
    1248
  • Разработка мобильного приложения для компании ZIPPY
    Разработка мобильного приложения для компании ZIPPY
    1110
  • Разработка мобильного приложения для компании Affhome
    Разработка мобильного приложения для компании Affhome
    1022
  • Разработка мобильного приложения для компании FLAVORS
    Разработка мобильного приложения для компании FLAVORS
    633

Реализация миграции данных при обновлении мобильного приложения

При обновлении мобильного приложения модель данных меняется не реже интерфейса. Клиенты приходят с типовой болью: после изменения схемы БД старые данные перестают корректно обрабатываться новой версией. Например, поле amount хранилось как REAL, а в новой версии требуется INTEGER центов — чтобы избежать floating-point ошибок при сравнении 100.10 vs 100.10. Или формат дат меняется с Unix timestamp в секундах на миллисекунды: 17000000001700000000000. Мы реализуем автоматическую миграцию данных на iOS и Android, гарантируя целостность и отсутствие потерь при любых трансформациях. Наш опыт включает проекты с объёмом данных свыше 500 000 записей, где критически важны скорость и надёжность. За годы мы провели более 30 успешных миграций для приложений в сферах финтех, логистика и медиа. Средняя экономия времени разработки за счёт готовых решений составляет до 40%.

Какие данные требуют миграции?

Конкретные сценарии из реальных проектов:

  • Поле amount хранилось как REAL (double), нужно перейти на INTEGER центов, чтобы избежать floating-point ошибок при сравнении. 100.1010010.
  • Поле status было INTEGER (0, 1, 2), теперь TEXT ("pending", "active", "completed"). Нужно смаппировать каждое число в строку.
  • Поле date было Unix timestamp в секундах, в новой версии — миллисекунды. 17000000001700000000000 (разница в 1000 раз).
  • JSON, хранившийся в TEXT-колонке, изменил структуру: старый {"items":[...]} → новый {"data":{"list":[...]}}.
  • Поле email ранее было необязательным, теперь стало уникальным ключом — требуется дедупликация и разрешение конфликтов.

Каждый из этих случаев — строковая трансформация всей таблицы внутри миграции. Для таблиц с 10 000+ записей прямое обновление может занять десятки секунд, поэтому важен выбор оптимальной стратегии.

Как мы реализуем миграцию в Room?

В Room для Android мы используем объекты Migration, которые выполняют преобразования вручную. Ключевой принцип — идемпотентность: каждую миграцию можно безопасно применить повторно.

val MIGRATION_3_4 = object : Migration(3, 4) { override fun migrate(db: SupportSQLiteDatabase) { // Конвертация суммы из float в integer cents db.execSQL(""" UPDATE transactions SET amount_cents = CAST(ROUND(amount * 100) AS INTEGER) """) // Конвертация статуса из int в string db.execSQL("UPDATE transactions SET status = 'pending' WHERE status_code = 0") db.execSQL("UPDATE transactions SET status = 'active' WHERE status_code = 1") db.execSQL("UPDATE transactions SET status = 'completed' WHERE status_code = 2") // Конвертация timestamp из секунд в миллисекунды db.execSQL("UPDATE events SET created_at = created_at * 1000 WHERE created_at < 9999999999") } } 

Условие WHERE created_at < 9999999999 защищает от повторного применения при ошибочном повторном запуске — дата в миллисекундах всегда больше этого числа. Аналогичный механизм используется в Core Data через mapping model.

Почему важно использовать batch-обновление для больших таблиц?

Если в таблице миллионы строк — обновление одним UPDATE может занять десятки секунд и заблокировать запуск. Батчевый подход разбивает операцию на транзакции по 500–1000 записей, что снижает нагрузку на SQLite и уменьшает время блокировки. Batch-обновление в 2,5 раза быстрее прямого UPDATE для таблиц с 100 000 записей.

val MIGRATION_4_5 = object : Migration(4, 5) { override fun migrate(db: SupportSQLiteDatabase) { var offset = 0 val batchSize = 1000 while (true) { val updated = db.compileStatement(""" UPDATE transactions SET metadata = transform_metadata(metadata) WHERE id IN ( SELECT id FROM transactions WHERE metadata_migrated = 0 LIMIT $batchSize ) """).executeUpdateDelete() if (updated == 0) break } } } 

Для таблиц с 10 000–500 000 строк такой подход даёт выигрыш во времени на 40–60% по сравнению с прямым UPDATE. При превышении 500 000 строк стоит применять ленивую миграцию.

Когда применять ленивую миграцию?

Если полная миграция занимает слишком долго для блокирующего выполнения при старте — более 5 секунд на младших устройствах.

// iOS — ленивая миграция при доступе к данным func fetchTransaction(id: String) -> Transaction { let raw = database.fetch(id: id) if !raw.isMigrated { let migrated = DataMigrator.migrate(raw) database.save(migrated) return migrated } return raw } 

Плюс: приложение стартует мгновенно. Минус: нужно поддерживать оба формата в коде, пока не все записи мигрированы. Фоновый WorkManager / BGProcessingTask постепенно мигрирует оставшееся — обычно за 2–3 дня в фоне.

Как тестировать трансформации?

Для Android используем MigrationTestHelper из Room:

@Test fun testAmountConversion() { val helper = MigrationTestHelper(instrumentation, AppDatabase::class.java) val db = helper.createDatabase("test.db", 3) db.execSQL("INSERT INTO transactions (id, amount) VALUES ('t1', 100.10)") db.close() val migrated = helper.runMigrationsAndValidate("test.db", 4, true, MIGRATION_3_4) val cursor = migrated.query("SELECT amount_cents FROM transactions WHERE id = 't1'") cursor.moveToFirst() assertEquals(10010, cursor.getInt(0)) } 

Особое внимание — граничным случаям: NULL значения, пустые строки, неожиданные форматы данных, которые реальные пользователи могут иметь в базе. Мы обязательно проверяем такие кейсы в тестах. Для iOS применяем NSMigrationManager с тестовыми NSManagedObjectModel разных версий.

Что делать при ошибке миграции?

SQLite поддерживает транзакции — весь onUpgrade автоматически оборачивается в транзакцию в Room. Если что-то падает, изменения откатываются. На iOS с Core Data — аналогично через NSMigrationManager. Однако откат не означает, что приложение работает нормально — при следующем запуске снова попытается мигрировать. Нужна обработка ошибок и отображение пользователю сообщения о проблеме. Мы добавляем такие проверки в процесс: логируем исключение, предлагаем повторную установку приложения из магазина.

Сравнение подходов к миграции

Подход Объём данных Время выполнения в onUpgrade Риски
Прямой UPDATE до 10 000 строк секунды Блокировка UI при большом объёме
Батчевый UPDATE 10 000 – 500 000 строк минуты Требует тюнинга batch size
Ленивая миграция от 500 000 строк не блокирует запуск Поддержка двух версий данных

Типы трансформаций и их сложность

Тип поля Пример Сложность
Число → число (масштабирование) REAL → INTEGER cents Низкая: один UPDATE
Число → строка INT код → TEXT Средняя: mapping через CASE
Временная метка (сек → мс) INT → INT * 1000 Низкая: один UPDATE с условием
JSON реструктуризация TEXT → TEXT Высокая: парсинг и сериализация
Дедупликация TEXT → UNIQUE Высокая: разрешение конфликтов

Что входит в работу

  1. Аудит данных в текущей БД: форматы, исключения, NULL-значения. Выявляем до 15% записей с аномалиями.
  2. Написание трансформаций с защитой от повторного применения (идемпотентность).
  3. Batch-обновление для таблиц от 10 000 записей с настраиваемым size (обычно 500–1000).
  4. Ленивая миграция для таблиц свыше 500 000 записей с фоновым воркером.
  5. Тесты на граничных случаях: пустая БД, частичная миграция, битые данные.
  6. Написание падающих тестов для каждого сценария.

Сроки

Простые UPDATE-трансформации (1–3 таблицы) — от 1 дня. Сложные преобразования JSON, ленивая миграция с фоновым воркером — от 2 до 4 дней. Стоимость рассчитывается индивидуально после аудита.

Получите консультацию по вашей базе данных — мы оценим объём работы и предложим оптимальную стратегию миграции. Закажите аудит текущей схемы данных и получите детальный отчёт с рекомендациями. Свяжитесь с нами для обсуждения деталей.