Миграции базы данных без простоя и паники

Когда бизнес говорит «нам нужно переехать на новую БД», разработчик слышит: «готовься к бессонной ночи, звонкам в 3 часа утра и риску остаться без работы». Миграция данных — это всегда игра с высоким уровнем ставок. Ошибка в одном скрипте или неверно рассчитанный размер индекса могут привести к каскадному отказу всей системы, когда приложение «ложится» под нагрузкой, а бэкапы восстанавливаются слишком медленно, чтобы уложиться в SLA.
Однако «zero downtime migration» (миграция без простоя) — это не магия, а четкий алгоритм. В этой статье мы разберем, как перевезти данные, не пугая пользователей и не доводя команду до нервного срыва.
Почему «просто выключить и перенести» больше не работает?
Раньше всё было проще: объявляли техническое окно на воскресенье, выключали сервер, переносили дамп и включали всё обратно. Но в эпоху микросервисов и глобального трафика окно в 4 часа превращается в огромные финансовые потери. Современный бизнес требует доступности 99.9% и выше.
Основная проблема «быстрой» миграции — непереносимость риска. Если вы обнаружите проблему через два часа после запуска, откат (rollback) может занять еще больше времени, чем сама миграция. Именно поэтому мы переходим к стратегии постепенного переключения.
Стратегия «Expand and Contract» (Расширение и Сжатие)
Самый надежный способ изменить схему данных или переехать на новый инстанс без остановки сервиса — это паттерн Expand and Contract. Вместо одного фатального шага мы разбиваем процесс на несколько безопасных этапов.
1. Этап расширения (Expand)
На этом этапе мы создаем новую структуру (новую таблицу, новую колонку или новый сервер), но продолжаем использовать старую.
-
- Дублирование записи: Приложение начинает писать данные и в старую, и в новую БД одновременно (Dual Write).
-
- Совместимость: Код должен уметь работать с обеими версиями схемы. Если запись в новую БД упала, приложение не должно «падать» — оно просто логирует ошибку, но продолжает работать со старой базой.
2. Этап синхронизации (Migration)
Пока новые данные текут в обе базы, нам нужно перенести «исторический хвост».
-
- Бэкап и перенос: Создается снимок данных на определенный момент времени (snapshot).
-
- Докатка (Catch-up): С помощью CDC (Change Data Capture) или простых скриптов переносятся все изменения, произошедшие с момента создания снимка.
3. Этап проверки (Verification)
Это критический момент, где большинство ошибается. Нельзя просто переключить рубильник. Нужно убедиться, что данные идентичны.
-
- Запуск фоновых проверок (consistency checks), которые сравнивают случайные выборки из старой и новой БД.
-
- Сравнение контрольных сумм или количества записей по ключевым индексам.
4. Этап сжатия (Contract)
Когда мы уверены, что новая база работает корректно, мы постепенно переводим чтение на новый инстанс.
-
- Сначала переключаем 1% трафика (Canary release).
-
- Затем 10%, 50% и, наконец, 100%.
-
- Только после этого старая база отключается, а код, отвечающий за двойную запись, вырезается из системы.
Технические подходы к синхронизации данных
В зависимости от объема данных и сложности схемы, выбор инструмента будет разным.
- Логическая репликация. Идеальный вариант для PostgreSQL или MySQL. Мы настраиваем репликацию на уровне строк, что позволяет переезжать даже между разными версиями СУБД.
- Change Data Capture (CDC). Использование инструментов вроде Debezium. Система слушает логи транзакций (WAL в Postgres или Binlog в MySQL) и в реальном времени переносит каждое изменение в новую систему через Kafka или RabbitMQ. Это позволяет избежать нагрузки на основную БД тяжелыми SELECT-запросами.
- Скриптовая миграция. Самый опасный, но иногда единственный путь. Написание собственных Python/Go скриптов, которые пачками (batching) переливают данные. Здесь критически важно использовать лимиты (
LIMIT/OFFSETили, что лучше, фильтрацию по ID), чтобы не забить память и не заблокировать таблицы (table locks).
Главные ловушки: где обычно всё ломается
Даже при наличии плана есть вещи, которые могут всё испортить. Вот список «граблей», на которые наступали почти все:
Блокировки таблиц (Locks). Команда ALTER TABLE на таблице в 100 миллионов строк может заблокировать запись на несколько часов.
-
- Решение: Используйте инструменты вроде
pt-online-schema-change(для MySQL) или создавайте новую таблицу, копируйте данные и переименовывайте её.
- Решение: Используйте инструменты вроде
Разрыв последовательностей (Sequences). Если вы используете автоинкремент, убедитесь, что счетчик в новой БД начинается с актуального значения, а не с единицы, иначе вы получите тысячи ошибок Unique Constraint Violation.
Сетевые задержки (Latency). Если новая база находится в другом регионе, двойная запись может замедлить ответы API в два раза.
-
- Решение: Асинхронная запись в новую БД через очередь сообщений.
Забытые индексы. Часто при миграции переносят данные, но забывают создать индексы на новом сервере. Результат — база «лежит» через 5 минут после переключения из-за Full Table Scan на каждом запросе.
Чек-лист для подготовки к «Дню X»
Чтобы миграция прошла без паники, перед стартом проверьте следующие пункты:
- План отката (Rollback Plan). Вы должны точно знать, как вернуться назад за 5 минут, если что-то пошло не так. Если вы не знаете, как откатиться — вы не готовы к миграции.
- Мониторинг. Настроены ли алерты на CPU, RAM, Disk I/O и количество открытых соединений на новом инстансе?
- Тестирование на стейджинге. Миграция должна быть прогнана на копии реальных данных (а не на «тестовых пяти записях»). Только так можно понять реальное время переноса.
- Коммуникация. Все ли стейкхолдеры знают о миграции? Есть ли у вас прямой контакт с администраторами сети и облачного провайдера?
Резюме
Миграция базы данных — это не про перенос байтов из точки А в точку Б. Это про управление рисками. Главный секрет «бесшовности» заключается в том, чтобы сделать процесс настолько дробным, чтобы каждый отдельный шаг был безопасным и легко обратимым.
Помните: лучше потратить две недели на настройку CDC и постепенный перенос, чем потратить одну ночь на попытки восстановить базу из битого бэкапа под крики разгневанного руководства. Спешка в работе с данными — кратчайший путь к катастрофе.

