Смена рельсов на полном ходу: как обновлять БД безопасно

Пять минут простоя платёжного сервиса в пик продаж, рассогласование данных клиентов после обновления CRM, неконтролируемый откат, который «съел» часть транзакций, — типичные последствия миграций, которые запускают как разовую техническую операцию. На практике миграция — это проект управления рисками, на период изменений система живёт в «двойном состоянии» (одновременно существуют старая и новая версии структуры или данных), и именно в этом переходном режиме чаще всего возникают инциденты.
Ниже — практические паттерны и контрольные точки, которые помогают проводить изменения предсказуемо, без длительных блокировок, без потери целостности и с понятным сценарием возврата в стабильное состояние.
Почему «окно простоя» больше не работает
Классический подход «написали скрипт — протестировали на стенде — остановили сервис на ночь — применили DDL — запустили обратно» плохо сочетается с непрерывной доставкой, SLA и требованиями к ИБ. Даже небольшая операция ALTER TABLE может занимать секунды на тестовом стенде и минуты (а иногда и часы) на продакшне — из‑за эксклюзивных блокировок, пересборки индексов, конкурирующих транзакций, особенностей планировщика, а главное — из‑за реальных объёмов данных и нагрузки.
Поэтому цель «без простоя» разумнее формулировать точнее и прагматичнее, а именно без длительных эксклюзивных блокировок, без потери данных и с управляемым откатом. Иными словами, речь не о магическом «ноль секунд влияния», а о том, чтобы влияние было ограниченным, измеримым и контролируемым.
Базовый принцип: постепенность и обратимость
Безопасная миграция почти всегда состоит из серии маленьких шагов. Каждый шаг должен одновременно удовлетворять трём условиям. Во‑первых, он должен быть совместим со старой версией приложения (чтобы релиз можно было выкатывать поэтапно и не «ломать» прод одним изменением схемы). Во‑вторых, он должен быть наблюдаем, для него заранее определены метрики, логи и критерии «нормальности», чтобы команда видела реальную картину, а не гадала по косвенным симптомам. В‑третьих, он должен быть обратим, что подразумевает понятный, проверенный и воспроизводимый план отката, который можно запустить под давлением времени и не усугубить ситуацию.
Такая постановка снижает риск «большого взрыва» и даёт ИБ возможность поставить контрольные точки на каждом этапе: кто меняет, что меняется, как это отслеживается и как возвращаемся назад при отклонениях.
Expand-Contract: рабочая классика (и ее реальная цена)
Паттерн Expand-Contract (расширение — переключение — сжатие) помогает менять схему без остановки сервиса, но требует дисциплины, дополнительных ресурсов и чёткого контроля переходного периода. Типовой сценарий выглядит так.
- Расширение (expand). Добавляем новую структуру рядом со старой (столбец, таблица или индекс). Приложение переводим в режим dual-write, запись идёт в обе версии, чтобы новая структура «набирала» актуальные изменения параллельно со старой.
- Перенос истории (backfill). Фоново переносим накопленные данные. Важно, после переноса нужен контроль целостности (например, выборочные сравнения, контрольные суммы), потому что сам факт выполнения backfill ещё не означает корректность результата.
- Переключение чтения (switch). Переводим приложение на чтение из новой структуры, но старую оставляем как страховку на период стабилизации. Это позволяет откатиться быстрее, если обнаружатся дефекты логики или неполный перенос данных.
- Сжатие (contract). Удаляем устаревшую структуру только после подтверждения стабильности и завершения контроля, иначе есть риск «отпилить мост» до того, как вы уверены, что переправа безопасна.
На практике «цена» этого паттерна складывается из нескольких факторов, и их полезно заранее проговорить не только инженерам, но и CISO или службе ИБ, потому что в период миграции меняется профиль риска.
| Фактор | Как проявляется | Что запросить/контролировать CISO |
| Нагрузка и SLA | Dual-write увеличивает количество операций записи и нагрузку на I/O. На больших таблицах backfill может конкурировать с продуктивным трафиком, повышать латентность и усиливать блокировки. | Нужно запросить нагрузочное тестирование на профиле, близком к продакшену, заранее определить лимиты скорости backfill (throttling), а также настроить алерты по латентности, росту очередей, блокировкам и времени выполнения транзакций. |
| Временный рост хранилища | На период миграции данные часто хранятся в двух местах. Рост может быть заметным для больших таблиц и индексов. | Следует учесть стоимость временного хранения в плане изменений и заранее проверить лимиты или квоты, а также оценить влияние на бэкапы и репликацию (объём и время). |
| Сложные изменения ключей и связей | PRIMARY KEY, FK и уникальные ограничения меняются тяжелее всего, здесь высокие риски блокировок, долгих перестроений и рассогласования (особенно при параллельных записях). | Важно подключить архитектора или DBA на этапе дизайна, заранее определить стратегию переключения и контроля целостности, а также договориться о критериях остановки при обнаружении расхождений. |
| Длинное «окно двойного состояния» | Пока существуют две версии данных, растёт операционный риск, усложняется поддержка, мониторинг, расследование инцидентов, а также повышается шанс «частичного» исправления (исправили в одном месте, забыли во втором). | Нужно заранее определить срок жизни двойного состояния, усилить аудит и контроль доступа на этот период, назначить ответственных за мониторинг, а также закрепить правило, что является «источником правды» на каждом шаге. |
Паттерны, которые помогают ИБ (и облегчают миграции)
1) Абстракция доступа к данным. Прямой доступ приложений к физическим таблицам усложняет изменения, любое DDL начинает «пробивать» весь контур, от запросов до отчётов. Слой абстракции (views, процедуры, репозиторий, ORM, API-шлюз) позволяет менять схему «под капотом» и одновременно встраивать контроль. Например, в одном месте проще включить логирование обращений, маскирование чувствительных полей и проверку прав, а также отследить, кто и как использует данные до и после переключения.
2) Application-first. Надёжнее сначала выкатить версию приложения, совместимую со старой схемой и умеющую работать с новой (если она появится), и только затем добавлять или активировать изменения в БД. Это уменьшает риск, что схема уже поменялась, а приложение ещё нет (или наоборот), и позволяет управлять переходом через feature-flags или конфигурацию, не устраивая «большой коммутатор» в полночь.
3) Репликация, blue-green для БД. В ряде случаев проще применить изменения на реплике и затем переключить роль. Такой подход особенно полезен, когда изменение потенциально тяжёлое, вы «вынесете» перестроения и проверки из основного контура. Однако это работает только при внимательном контроле задержки репликации, проверках целостности и заранее отработанном плане переключения или отката.
Безопасность и комплаенс в период «двойного состояния»
Период одновременного существования старых и новых структур — самое уязвимое место миграции. В это время поверхность атаки расширяется (структур больше, путей доступа больше, ошибок конфигурации тоже больше), а расследования усложняются. Поэтому контрольные точки стоит формулировать заранее и сделать их частью плана изменений.
С точки зрения доступа и привилегий на время миграции разумно ограничить прямые подключения к БД и выдавать только минимально необходимые права, чем меньше «ручных» действий, тем меньше неучтённых отклонений. Любые ручные изменения должны выполняться по оформленному запросу с фиксацией исполнителя и причины, иначе в момент инцидента вы не восстановите цепочку событий. Далее, важно обеспечить аудит DDL и DML, логировать все изменения схемы и операции над мигрируемыми объектами, выгружать логи в SIEM или хранилище аудита и обеспечивать неизменяемость записей (WORM, append-only). Это одновременно помогает расследованиям и дисциплинирует выполнение изменений в рамках процесса.
Отдельный блок — контроль целостности. Нужно заранее запланировать проверки расхождений между старой и новой версиями данных (выборочные сравнения, контрольные суммы, сверка агрегатов, контроль дубликатов или потерь) и заранее определить критерии остановки миграции, что считается допустимым отклонением, а что является стоп-фактором.
Если меняются поля с персональными, платёжными или коммерческими данными, важно не допустить ситуации «сначала создадим новую структуру, а шифрование или маскирование включим потом». Политики шифрования, маскирования и хранения должны распространяться на новую структуру сразу, потому что именно переходный период часто становится источником компрометации.
Наконец, для контуров с персональными данными необходимо заранее продумать права субъектов и удаление. Нужно понимать, как запросы на исправление или удаление будут корректно применяться в обеих версиях данных до завершения миграции. Иначе вы рискуете получить «частично удалённые» данные и юридически, и технически опасный разрыв.
Откат: что считать «планом эвакуации»
План отката — это не только «вернуть схему назад». Он должен отвечать на главный вопрос, что делать с данными, которые появились после переключения, и как быстро вернуть сервис в рабочее состояние без потерь и без наращивания хаоса. По сути, это заранее подготовленная «эвакуация» из переходного режима.
Минимальные требования к откату следующие. Прежде всего, нужна идемпотентность, повторный запуск скриптов не должен ухудшать состояние, поэтому используются проверки существования объектов и версионирование. Скрипт отката должен адаптироваться к текущему состоянию, он обязан учитывать, на каком шаге остановилась миграция, иначе откат сам станет источником инцидента. Откат должен сохранять данные, предусмотрите обратный перенос (backfill обратно) или временный режим dual-read и dual-write, чтобы не потерять изменения, сделанные пользователями после переключения. Наконец, откат должен быть проверен на тех же данных, его нужно репетировать на копии продакшн-профиля и иметь измеримое RTO и RPO, а не «кажется, вернёмся за полчаса».
Процесс и контроль: что закрепить, чтобы миграции были управляемыми
Технические паттерны не спасают без процесса изменений. Чтобы миграции были повторяемыми и управляемыми, минимальный набор организационных практик стоит закрепить явно.
Нужен единый стандарт миграций, шаблон описания, оценка влияния на SLA, план наблюдаемости, план отката, ответственные и коммуникации. Это превращает миграцию из «магии конкретного инженера» в воспроизводимую процедуру. Далее важно правило «миграция = миграция + откат», в репозиторий попадают только парные сценарии, прошедшие ревью и тесты, чтобы откат не оказался «забытым» в момент, когда он нужен больше всего.
Отдельно стоит закрепить запрет на «починку продакшна без следов». Любые операции уровня repair или force должны оформляться как инцидент или изменение и оставлять аудируемый след. Это не бюрократия ради бюрократии, это способ защититься от необратимых действий и обеспечить разбор полётов.
И, наконец, критично тестирование на реалистичных данных и конфигурациях. Объёмы, индексы, локали, версии СУБД, параметры блокировок и репликации должны быть близки к боевым, иначе вы тестируете не миграцию, а оптимистичный сценарий, который редко встречается в реальности.
Короткий чек-лист для CISO перед стартом миграции
- Перед стартом миграции CISO важно зафиксировать несколько вещей в понятных и проверяемых формулировках. Во-первых, должно быть понимание критичности, какие сервисы и данные затронуты, какой допустимый RTO и RPO и какая деградация сервиса приемлема (например, рост латентности, частичная функциональность). Во-вторых, нужен план, шаги миграции, критерии перехода между шагами и заранее определённый срок двойного состояния, чтобы переходный режим не стал «вечным». В-третьих, должна быть наблюдаемость, метрики блокировок, латентности, ошибок, объёмов, настроенные алерты и назначенные ответственные дежурные, которые будут реагировать, а не «узнают утром». В-четвёртых, должны быть закрыты аудит и доступы, кто может выполнять DDL и DML, где фиксируются действия, куда уходят логи и как обеспечивается их сохранность. И, наконец, откат должен быть отрепетирован, подтверждены время отката и сохранность данных на тестовом прогоне, а не на словах. Откат отрепетирован: подтверждены время отката и сохранность данных на тестовом прогоне.
Заключение
Миграции «без простоя» — это не один удачный скрипт, а сочетание архитектурных паттернов, наблюдаемости и процесса управления изменениями. Инвестиции в эту дисциплину (время инженеров, инструменты мониторинга, репетиции отката) обычно на порядки ниже стоимости простоя, порчи данных или инцидента ИБ в период перехода. Чем раньше миграции становятся стандартной управляемой практикой, тем меньше они похожи на рискованную «ночную операцию», и тем предсказуемее система переживает изменения.
Статью подготовила команда GitFlic (входит в «Группу Астра»)
