Короткий ответ
Основной принцип — любое изменение схемы должно оставаться совместимым как минимум с предыдущей версией кода на протяжении переходного периода (backward-compatible), что достигается аддитивными изменениями (новые nullable-колонки/таблицы вместо немедленного удаления/переименования старых) и явным разделением «расширения» схемы от «сжатия» (expand/contract) на отдельные релизы.
Как это работает подробнее
При rolling deploy и при необходимости откатить релиз одновременно могут работать как минимум две версии кода с одной и той же БД; совместимость означает, что старая версия кода не должна падать на новой схеме, а новая версия должна корректно работать даже при откате кода.
Сравнение
- Компромисс. Полностью безопасная эволюция (expand/contract, многоэтапные релизы) требует больше времени и дисциплины по сравнению с «быстрым» прямым изменением схемы; критерий выбора — насколько критичен сервис к простою и как часто требуется откат, и готова ли команда поддерживать временно двойственный код на переходный период.
Пример кода
Сценарий
Запрос на изменение: переименовать "status" в "order_status" и поменять набор допустимых значений.
Безопасный план:
1) Добавить новую колонку order_status, дублировать запись в обе колонки на уровне приложения.
2) Выпустить новую версию API с полем order_status как optional, старое поле status помечено
deprecated, но ещё отдаётся.
3) После миграции всех потребителей API на новое поле — прекратить запись в старую колонку
и удалить её отдельным релизом.
Риск при пропуске шагов: клиент API, который не обновился, получит неожиданное отсутствие поля
status и сломается без предупреждения.Что использовать на практике
- Практика. Безопасные паттерны — добавление новых nullable-колонок/таблиц, отдельные релизы на «удаление» только после полной уверенности, что старый код больше не используется; версионирование контрактов API позволяет потребителям переходить постепенно.
Подводные камни
- Ошибка. Совмещают несовместимое изменение схемы и деплой кода в один шаг, рассчитывая на «мгновенность» деплоя; не тестируют сценарий отката релиза отдельно от сценария «вперёд» — откат кода на старую версию при уже применённой новой миграции может оказаться невозможным.