Москва: проверенные б/у ноутбуки с гарантией и проверкой перед оплатой
+7 906 722-94-45

Главная → Статьи → Миграция данных: практика переноса между схемами

Миграция данных: перенос между схемами без потери и без простоя

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

Прямой ответ

Миграция данных — перенос значений из одной структуры в другую. В отличие от изменения схемы, которое выполняется одной командой, перенос данных обрабатывает существующие строки и занимает время, пропорциональное объёму.

Порядок работ состоит из пяти этапов:

1. Подготовка: новая структура создана, код читает и пишет в обе.
2. Перенос: существующие данные копируются в новую структуру.
3. Проверка: сверка количества и содержимого.
4. Переключение: код читает только из новой структуры.
5. Завершение: старая структура удаляется.

Ключевое правило — старая структура остаётся доступной до завершения проверки. Удаление до сверки делает откат невозможным, а ошибка в преобразовании обнаруживается по обращению пользователя.

Перенос выполняется пакетами, а не одной командой:

BATCH = 5000
last_id = 0
while True:
    rows = fetch_batch(source, after_id=last_id, limit=BATCH)
    if not rows:
        break
    write_batch(target, [transform(r) for r in rows])
    last_id = rows[-1].id
    save_checkpoint(last_id)

Сохранение контрольной точки позволяет продолжить после сбоя, а не начинать перенос заново; о механизме — в статье про отслеживание прогресса.

Три требования к функции преобразования.

1. Детерминированность. Одинаковая исходная строка даёт одинаковый результат при повторном вызове. Иначе повторный прогон даёт другой результат, и сверка не работает.

2. Идемпотентность записи. Повторная обработка строки не создаёт дубликат. Запись выполняется через вставку с обновлением при конфликте либо по первичному ключу.

3. Обработка недопустимых значений. Исходные данные содержат значения, не подходящие под новые ограничения. Преобразование определяет поведение явно: пропуск, значение по умолчанию либо перенос в список исключений.

Отдельный вопрос — запись во время переноса. Данные продолжают изменяться, поэтому перенос существующих строк дополняется передачей изменений; о механизме — в статье про двойную запись.

Изменение схемы под данные выполняется по схеме expand-contract: сначала добавляется новая структура, затем переносятся данные, затем удаляется старая; о подходе — в статье про expand-contract.

Практика: проведение миграции данных

1. Оцените объём и время. Перенос миллиона строк и миллиарда строк — разные задачи по подходу и длительности; о планировании — в статье про оценку нагрузки.

2. Выполняйте перенос пакетами. Одна транзакция на весь объём удерживает блокировки и прерывается по таймауту.

3. Сохраняйте контрольные точки. Продолжение после сбоя с последней позиции экономит часы повторного переноса.

4. Проверяйте количество и содержимое. Совпадение числа строк не означает корректность преобразования; о методике — в статье про сверку.

5. Ведите список исключений. Строки, которые не удалось преобразовать, фиксируются отдельно, а не пропускаются молча.

6. Троттлите нагрузку на базу. Перенос создаёт дополнительную нагрузку, которая влияет на работающий сервис; о блокировках — в статье про deadlock-и.

7. Зафиксируйте точку невозврата. Момент, после которого откат невозможен, определяется заранее и фиксируется в плане.

8. Подготовьте резервную копию до начала. Откат к прежнему состоянию требует точки восстановления; о стратегиях — в статье про резервное копирование.

Рекомендации:

  1. Не совмещайте миграцию данных с релизом функциональности. Отдельное изменение проще откатить и разобрать при проблеме.
  2. Репетируйте на копии продуктивных данных. Объём и распределение значений влияют на время и на число исключений.
  3. Измеряйте скорость переноса. Прогноз завершения нужен для планирования переключения.
  4. Проверяйте идемпотентность повторным прогоном. Повторный запуск не должен изменять результат.
  5. Документируйте порядок отката. Процедура возврата описывается до начала переноса, а не в момент проблемы.

Практический сценарий: перенос 40 миллионов строк с изменением структуры

Контекст: поле адреса в виде одной строки требовалось разделить на структурированные компоненты. Таблица содержала 40 миллионов строк и использовалась работающим сервисом.

  1. Диагностика. Прямое обновление всей таблицы оценивалось в несколько часов с удержанием блокировок. Около двух процентов значений не поддавались разбору по ожидаемому формату.
  2. Причина. Изменение структуры планировалось одной командой без учёта объёма и некорректных значений. План отката отсутствовал.
  3. Действия. (а) Добавили новые колонки, оставив прежнюю доступной; (б) перенос выполнили пакетами по пять тысяч строк с сохранением контрольной точки; (в) двойную запись включили до начала переноса, чтобы новые изменения попадали в обе структуры; (г) неразобранные значения собрали в отдельную таблицу и обработали вручную; (д) после сверки количества и выборочной проверки содержимого чтение перевели на новые колонки; (е) прежнюю колонку удалили через две недели после переключения.
  4. Результат. Перенос занял девять часов без влияния на работу сервиса, а откат оставался возможным до момента удаления прежней колонки.

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

FAQ

Сколько длится миграция данных? Пропорционально объёму и скорости записи. Оценка выполняется на копии продуктивных данных, а не по числу строк.

Можно ли перенести данные одной командой? Технически да для небольших таблиц. Для миллионов строк одна транзакция удерживает блокировки и прерывается по таймауту.

Что делать со строками, которые не преобразуются? Фиксировать в списке исключений и обрабатывать отдельно. Молчаливый пропуск приводит к потере данных.

Когда удалять старую структуру? После переключения чтения и подтверждения корректности. Удаление до проверки делает откат невозможным.

Источники: PostgreSQL docs (COPY), Alembic docs, Martin Fowler (Parallel Change) — ссылки в шапке.