Базы данных
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 подхода?