Как произвести рефакторинг при смене названия поля в базе данных?
Что проверяют
Понимаете ли вы, что переименование колонки ломает не только ваш код, но и всё, что обращается к базе в момент деплоя. Интервьюер ждёт план без простоя, а следом обычно спрашивает, что будет с запущенными экземплярами старой версии приложения.
Как отвечать
Сначала выясните, нужно ли вообще трогать базу. Если имя плохое только в коде, переименуйте атрибут модели и оставьте колонку: в Django через db_column='old_name', в SQLAlchemy через mapped_column("old_name"). Имя поля в API тоже задаётся отдельно, в DRF через source=, и контракт с фронтендом не ломается.
Если колонку всё-таки переименовывают, есть два пути:
- простой: миграция
RenameFieldв Django (makemigrationsсам спросит, было ли это переименование) илиop.alter_column(..., new_column_name=...)в Alembic. В PostgreSQL это правка метаданных, но под эксклюзивной блокировкой, поэтому ставятlock_timeout. Подходит, если на время деплоя приложение можно остановить; - без простоя (expand/contract): добавить новую колонку, писать в обе, перенести старые данные пачками, переключить чтение, убрать запись в старую и только следующим релизом удалить её. Каждый шаг совместим и с текущей, и с предыдущей версией кода.
Затем поиск зависимостей: сырой SQL, .values() и .filter() со строковыми именами, фикстуры, отчёты, ETL и соседние сервисы, которые читают ту же базу. Для внешних потребителей на переходный период можно оставить представление со старым именем.
Проверка: миграция и downgrade прогоняются на копии прод-базы, тесты зелёные на обеих версиях схемы.
Где спотыкаются
Доверяют автогенерации Alembic. Она не видит переименований и создаёт drop_column плюс add_column, то есть данные молча пропадают.
Переименовывают колонку одним релизом при rolling-деплое. Пока старые поды не заменены, они шлют запросы к несуществующей колонке и падают.
Ищут старое имя только в моделях. Строки в сырых запросах, шаблонах и настройках BI остаются и ломаются уже после релиза.