Вопрос с собеседования · System design

Нужно переименовать колонку name в full_name без простоя при rolling-выкатке. Какая последовательность верна?

MiddleВыкатка и миграции
Ещё спрашивают так:
  • Как переименовать колонку без простоя?
  • Что такое parallel change?
Коротко

Expand–contract в пять шагов: добавить full_name → писать в обе колонки → перелить старые данные порциями → читать из новой → удалить name отдельным поздним релизом.

  • Прямой RENAME мгновенно ломает работающие экземпляры старой версии
  • Бэкфилл — пачками, а не одним UPDATE: длинная транзакция держит блокировки и раздувает таблицу
  • Индексы — CREATE INDEX CONCURRENTLY

А ещё На любом шаге можно остановиться и откатиться

Подробно

Почему не RENAME. В момент переименования старые экземпляры продолжают писать в name и падают. Даже если выкатка мгновенная, откат вернёт код, который не знает full_name.

Шаги:

  1. Expand — миграция ADD COLUMN full_name (nullable, без значения по умолчанию, чтобы не переписывать таблицу). Код не меняется.
  2. Двойная запись — релиз кода, который пишет в обе колонки, а читает ещё старую. После выкатки все новые и изменённые строки имеют обе.
  3. Бэкфилл — перенос старых строк порциями: UPDATE ... SET full_name = name WHERE id BETWEEN ... AND full_name IS NULL по несколько тысяч, с паузами. Один большой UPDATE держит блокировки, генерирует огромный WAL и отставание реплик.
  4. Переключение чтения — релиз, который читает full_name (и пишет ещё в обе — на случай отката).
  5. Contract — когда старых версий нигде нет и откат на них не нужен: код перестаёт писать в name, затем отдельной миграцией DROP COLUMN name.

Детали: ограничения (NOT NULL) добавлять после бэкфилла, в PostgreSQL — через CHECK ... NOT VALID и последующий VALIDATE, чтобы не блокировать таблицу; индексы — CONCURRENTLY; инструменты вроде gh-ost или pg-osc для тяжёлых изменений.

Что хотят услышать

  • Почему прямой RENAME ломает rolling-выкатку.
  • Пять шагов expand–contract по порядку.
  • Бэкфилл порциями и неблокирующие индексы.
  • Удаление старого — последним отдельным релизом.

Частые ошибки

  • Делать бэкфилл одним UPDATE на всю таблицу.
  • Удалять старую колонку в том же релизе, где переключили чтение.

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

Один верный вариант. Подумайте, потом откройте ответ.

Показать варианты и ответ
  • ✗Выполнить ALTER TABLE ... RENAME COLUMN вместе с выкаткой нового кода
  • ✓Новая колонка → запись в обе → перелив данных → переключение чтения → удаление старой позже
  • ✗Создать новую таблицу, скопировать данные и переключиться одним релизом
  • ✗Переименовать колонку ночью, когда нагрузка минимальна

Что спросят дальше

  • Почему фазу удаления откладывают?
  • Чем помогают Flyway и Liquibase и чего они не решают?

Разбор темы

Связанные вопросы

Партнёр платформы

Разбор собеседования с sotto

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

Разбор собеседования