Базы данных

Database Migrations

GitHub в 2015 году должен был переименовать колонку в таблице с 2 миллиардами строк. Простой ALTER TABLE заблокировал бы сайт на часы. Инженеры написали gh-ost - инструмент для MySQL online schema changes. Сегодня gh-ost используется Twitter, Shopify, WeChat для zero-downtime миграций.

  • **GitLab**: каждая migration проходит через 3+ деплоя (expand, migrate, contract) - 50K self-hosted инсталляций без downtime
  • **GitHub**: gh-ost для MySQL online schema changes - 1.3TB таблица мигрирована за 16 часов без остановки
  • **Stripe**: data migrations на 100M+ строк как background jobs с мониторингом прогресса

Инструменты миграций

Database migration - версионированное изменение схемы БД. Код и схема эволюционируют вместе. Инструменты: Flyway (Java, SQL-based), Liquibase (Java, XML/YAML/SQL), Alembic (Python/SQLAlchemy), Prisma Migrate (TypeScript), golang-migrate. Каждая миграция = атомарный шаг вперёд (и опционально назад).

Checksum integrity: Flyway/Liquibase хешируют каждую применённую миграцию. Если уже применённый файл изменился - стоп и ошибка. Это защищает от случайного редактирования исторических миграций.

Почему не рекомендуется редактировать уже применённую миграцию?

Zero-Downtime DDL

Некоторые DDL операции в PostgreSQL берут ACCESS EXCLUSIVE lock на таблицу - блокируют все READ и WRITE пока выполняются. ADD COLUMN DEFAULT, CREATE INDEX (не CONCURRENTLY), ALTER COLUMN TYPE - могут занять минуты на большой таблице и вызвать downtime.

strong_migrations (Ruby gem) автоматически проверяет Rails миграции на unsafe operations. Shopify, GitHub используют его в CI. При попытке опасного DDL - ошибка с инструкцией как сделать безопасно.

Нужно добавить индекс на таблицу 50M строк в продакшне без даунтайма. Какой метод?

Expand-Contract паттерн

Expand-Contract (также Blue-Green schema migration) - паттерн для изменения схемы без даунтайма при rolling deployment (несколько версий приложения работают одновременно). Три фазы: Expand (добавить новую структуру, старая продолжает работать), Migrate (двойная запись, бэкфилл), Contract (удалить старую структуру после перехода всех инстансов).

GitLab задокументировала свой процесс zero-downtime migrations: каждое DDL изменение проходит через 3-4 отдельных MR (merge request) и деплоя. Это занимает дни, но garantirует отсутствие downtime для 50,000+ self-hosted инсталляций.

Expand-Contract: на фазе Expand добавлена новая колонка. Какое поведение приложения правильное?

Data Migrations

Data migration - изменение существующих данных в БД. В отличие от schema migration, может занимать часы на больших объёмах. Правила: всегда батчами (не один большой UPDATE), с паузами между батчами, идемпотентно (безопасно перезапустить), отдельно от schema migration.

Online schema changes: pt-online-schema-change (Percona) и gh-ost (GitHub) для MySQL. Создают shadow таблицу с новой схемой, копируют данные батчами, переключают таблицы через RENAME. GitHub migrated 1.3TB таблицы за 16 часов без downtime используя gh-ost.

Data migration запущена. После 2 часов сервер упал. Миграция обработала 70% строк. Что произойдёт при перезапуске?

Rollback стратегии

Откат schema migration - редкий но важный сценарий. Простые DDL операции (CREATE TABLE, ADD COLUMN) легко откатываются. Сложные (ALTER COLUMN TYPE с конвертацией данных) требуют reverse migration. Лучшая стратегия: forward-only migrations с expand-contract - нет необходимости откатывать схему.

GitLab политика: каждая миграция должна быть safe для rollback без потери данных. Добиваются через expand-contract: при откате приложения на предыдущую версию - старая схема всё ещё работает (Contract фаза ещё не выполнена).

Можно редактировать применённые миграции для исправления ошибок

Применённые миграции - immutable история. Для исправления создают новую migration. Редактирование старой нарушит checksum и сломает деплои.

Миграции - аудит-трейл изменений схемы. Их неизменность гарантирует что состояние БД на prod совпадает с историей миграций. Любые правки только вперёд (forward-only).

Наиболее надёжная стратегия избежать необходимости rollback migrations?

Итоги

  • **Zero-downtime DDL**: ADD COLUMN nullable сначала, CREATE INDEX CONCURRENTLY, бэкфилл батчами - не один большой UPDATE
  • **Expand-Contract**: 3 фазы (add new, double-write+backfill, drop old) для renaming/restructuring без downtime
  • **Data migrations**: идемпотентно, батчами с паузами, отдельно от schema changes

Связанные темы

Миграции - часть операционной зрелости продукта:

  • Мониторинг БД — Долгие миграции нужно мониторить: lock wait time, progress, производительность БД во время миграции
  • Резервное копирование — Перед сложной миграцией всегда делать backup - точка отката при катастрофе
  • Транзакции — DDL в PostgreSQL транзакционный; CREATE INDEX CONCURRENTLY нельзя внутри транзакции

Вопросы для размышления

  • Как безопасно изменить тип колонки amount с DECIMAL на INTEGER (центы) на таблице 100M строк в продакшне?
  • Expand-Contract требует 3 отдельных деплоя. Как управлять этим процессом в команде из 10 разработчиков?
  • Когда оправдан downtime для schema migration вместо zero-downtime подхода?

Связанные уроки

  • sd-10-microservices
Database Migrations

0

1

Войти