сеньорчикОткрыть в Telegram
← вся теориятеория к собесу · Модель данных

Миграции и совместимость

Миграции и совместимость

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

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

// Формулировки: «как переименовать колонку без простоя?», «почему новую колонку делают необязательной?», «миграция на 50 миллионов строк»

Три шага для новой обязательной колонки

Обязательная колонка требует значения для каждой существующей строки - иначе база просто не даст её создать. А осмысленного значения для прошлых записей обычно нет: если раньше поле «канал привлечения» не заполняли, то и взять его для старых клиентов неоткуда.

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

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

// Аналитик тут нужен ровно затем, чтобы этот выбор состоялся осознанно. Без него разработчик проставит «прочее» всем миллионам старых записей, и через год никто не сможет отличить настоящее «прочее» от заглушки.

Обратная совместимость и приём расширить-сжать

Совместимость определяется не по документации, а по работающему коду. При постепенном обновлении старые и новые экземпляры приложения какое-то время живут одновременно и ходят в одну и ту же базу. Значит, схема обязана устраивать обе версии сразу.

Отсюда следует простая классификация. Добавление необязательной колонки безопасно: старый код её не видит и не расстраивается. Удаление и переименование - нет: старый код обратится к тому, чего уже нет, и упадёт.

Переименование делают в четыре шага. Добавить новую колонку. Настроить запись в обе - старая версия пишет в свою, новая в обе. Перенести накопленное и переключить чтение на новую. И только когда старая версия нигде не работает - удалить прежнюю колонку.

// Медленнее, зато на каждом шаге система остаётся работоспособной для обеих версий кода, и в любой момент можно остановиться. Одношаговое переименование роняет ещё живые экземпляры старой версии - причём не все сразу, а по мере того, как на них попадают запросы, что делает картину особенно запутанной.

Тихие потери и большие объёмы

Смена типа с потерей точности не даёт никакой ошибки. Миграция проходит успешно, приложение работает, тесты зелёные, а копейки во всех суммах округлились. Всплывает это на сверке или в отчёте, иногда через месяцы, когда исходные значения уже неоткуда взять - они перезаписаны.

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

// И всегда заранее продумывают план отката с честным указанием точки невозврата - момента, после которого вернуться уже нельзя. Удалённые данные не воскресают, потерянная точность не восстанавливается. Знать, где эта точка, надо до начала работ, а не в процессе.

Как отвечать: «Нужно переименовать колонку в большой рабочей таблице. Как без простоя?»

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

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

На чём валятся

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

Проверьте себя

Пять вопросов из банка по этой подтеме. Всего их 12, остальные разбираются в тренажёре.

  1. #ana_dm_migrations1 / 5
    Нужно переименовать колонку в большой рабочей таблице. Как это делают без простоя?
    A)Переименовать сразу в момент релиза
    B)Добавить новую, дублировать запись, потом убрать старую
    C)Остановить сервис на время операции
    D)Создать представление с новым именем и оставить всё как есть
    показать ответ и разбор
    +B)Добавить новую, дублировать запись, потом убрать старую

    // разбор: Приём известен как расширить-сжать: сначала добавляют новую колонку и пишут в обе, потом переносят накопленное и переключают чтение, и только затем, когда старая версия кода нигде не работает, удаляют прежнюю колонку. Каждый шаг совместим с обеими версиями приложения.

  2. #ana_dm_migrations2 / 5
    Что аналитик обязан описать для миграции, разделяющей одно поле на два?
    A)Ожидаемое время выполнения операции
    B)Размер таблицы после изменения
    C)Имя разработчика, который её выполнит
    D)Правило разбора и судьбу остатка
    показать ответ и разбор
    +D)Правило разбора и судьбу остатка

    // разбор: Разделение поля «ФИО» на части упирается в реальность: двойные фамилии, отсутствующее отчество, мусор вроде «не указано». Нужно правило разбора и решение по остатку — оставить в резервном поле, пометить на ручную проверку или отклонить. Без этого миграция молча испортит часть данных.

  3. #ana_dm_migrations3 / 5
    Миграция изменила тип поля и потеряла точность. Когда это обнаружат?
    A)Сразу при выполнении миграции
    B)На сверке данных или в отчётности
    C)При следующем резервном копировании
    D)При перезапуске приложения
    показать ответ и разбор
    +B)На сверке данных или в отчётности

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

  4. #ana_dm_migrations4 / 5
    Зачем к миграции готовят план отката?
    A)Этого требуют правила оформления релизов
    B)Чтобы ускорить выполнение самой миграции
    C)Чтобы вернуться к рабочему состоянию при сбое
    D)Чтобы уменьшить нагрузку на базу данных
    показать ответ и разбор
    +C)Чтобы вернуться к рабочему состоянию при сбое

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

  5. #ana_dm_migrations5 / 5
    Миграция на пятьдесят миллионов строк идёт часами и блокирует таблицу. Что предложить?
    A)Выполнить её в ночное окно целиком
    B)Разбить на пакеты и выполнять постепенно
    C)Увеличить таймаут блокировки в настройках
    D)Отключить проверки целостности на время
    показать ответ и разбор
    +B)Разбить на пакеты и выполнять постепенно

    // разбор: Обработка порциями по несколько тысяч строк с паузами не держит длинную блокировку и не раздувает журнал транзакций. Процесс идёт дольше по календарю, зато система остаётся живой, а при сбое продолжается с последней обработанной порции. Ночное окно перестаёт спасать, как только объём перерастает его длительность.

дальше

Теорию прочитали. Навык ставится повторением

В Сеньорчике эта подтема идёт в ежедневных сессиях: движок возвращает её, пока ответы не станут уверенными, и ведёт прогресс отдельно по каждой подтеме. Теория внутри тоже бесплатна, лимит только на количество вопросов в день.