Что происходит после успешного выполнения миграции базы данных
Миграция базы данных завершается без ошибок. Пайплайн показывает зелёный статус. Команда выдыхает с облегчением. Но через час пользователи начинают жаловаться, что страницы загружаются медленно. Некоторые запросы уходят в таймаут. Несколько API-вызовов возвращают 500-ю ошибку. Миграция прошла успешно технически, но что-то пошло не так под капотом.
Этот сценарий встречается чаще, чем большинство команд ожидает. Миграция, завершившаяся без исключения, — это не то же самое, что миграция, оставившая систему в здоровом состоянии. Разница между этими двумя исходами — именно то, что призвана выявить пост-миграционная верификация.
Почему кодов успеха недостаточно
Большинство инструментов миграции возвращают нулевой код возврата, когда завершаются без ошибок. Это говорит вам, что SQL выполнился и внутренняя таблица отслеживания инструмента была обновлена. Это не говорит вам, хорошо ли новая схема работает с приложением, изменилась ли производительность запросов или оставила ли миграция блокировки.
Миграция может быть технически успешной, но всё равно нанести реальный ущерб. Добавление столбца со значением по умолчанию может заблокировать большую таблицу на минуты. Изменение типа столбца может вынудить базу данных переписывать строки, что замедляет параллельные запросы. Добавление индекса может помочь одному запросу, но сломать план выполнения для другого. Ни одна из этих проблем не проявляется в коде возврата инструмента миграции.
Пост-миграционная верификация — это практика проверки фактического состояния базы данных и приложения после выполнения миграции. Она превращает слепое развёртывание в информированное.
Правильно проверяйте статус миграции
Первое, что нужно проверить — завершилась ли миграция полностью или остановилась на полпути. Некоторые инструменты применяют миграции пакетами. Если миграция упала на третьем пакете, первые два пакета уже изменили базу данных. Код возврата может быть ненулевым, но ущерб уже частичный.
Посмотрите на таблицу отслеживания инструмента миграции или его подробные логи. Выясните, какие именно операторы были применены и на каком этапе процесс остановился. Эта информация подскажет, находится ли база данных в консистентном состоянии или требуется ручная очистка перед повторной попыткой.
Не полагайтесь только на код возврата. Некоторые миграции выдают предупреждения, которые не являются фатальными, но указывают на потенциальные проблемы, такие как устаревший синтаксис или неявные преобразования типов. Логируйте эти предупреждения и включайте их в отчёт пайплайна.
Сравнивайте задержку запросов до и после
Изменения схемы могут повлиять на то, как база данных выполняет запросы. Столбец, добавленный в таблицу, может заставить планировщик запросов выбрать другой индекс или полное сканирование таблицы. Изменение типа данных может отключить использование индекса для определённых сравнений.
Пайплайн должен выполнять набор репрезентативных запросов к базе данных до и после миграции. Сравните задержку для каждого запроса. Если какой-либо запрос показывает значительное увеличение, это сигнал, что миграция изменила план выполнения таким образом, который вредит производительности.
Сосредоточьтесь на запросах, которые приложение использует наиболее часто или которые известны как чувствительные к производительности. Не выполняйте тяжёлые аналитические запросы для этой проверки. Держите верификационные запросы лёгкими, чтобы не создавать нагрузку на базу данных во время окна развёртывания.
Проверяйте блокировки, которые не снялись
Миграции, изменяющие схему, часто требуют захвата блокировок на таблицах или строках. Большинство блокировок снимаются по завершении миграции, но не всегда. Долго выполняющаяся транзакция, неправильно закрытое соединение или миграция, ушедшая в таймаут, могут оставить блокировки.
После завершения миграции проверьте базу данных на наличие активных блокировок. Если блокировки всё ещё удерживаются, приложение будет испытывать таймауты или накопление очереди при попытке доступа к затронутым таблицам. Пайплайн также должен логировать, как долго удерживались блокировки во время миграции. Если блокировка удерживалась более нескольких секунд на production-таблице, это стоит расследовать, даже если она в конечном итоге была снята.
Выполните этот запрос, чтобы увидеть, остались ли какие-либо блокировки на таблице, которую вы мигрировали:
SELECT
pg_locks.pid,
pg_locks.mode,
pg_locks.granted,
pg_class.relname,
pg_stat_activity.query,
pg_stat_activity.state,
pg_stat_activity.wait_event_type || ': ' || pg_stat_activity.wait_event AS wait
FROM pg_locks
JOIN pg_class ON pg_locks.relation = pg_class.oid
JOIN pg_stat_activity ON pg_locks.pid = pg_stat_activity.pid
WHERE pg_class.relname = 'your_table_name'
AND pg_locks.granted = true;
Если возвращены какие-либо строки, миграция оставила блокировки. Изучите столбцы query и state, чтобы понять причину.
Проверяйте количество строк для миграций, изменяющих данные
Некоторые миграции делают больше, чем просто изменение схемы. Они заполняют новые столбцы значениями по умолчанию, перемещают данные между таблицами или очищают дубликаты. Эти операции могут молча пропускать строки, если логика миграции имеет краевые случаи или если данные не соответствуют ожидаемому формату.
После таких миграций сравните фактическое количество строк с ожидаемым. Например, если миграция должна была заполнить новый столбец для всех существующих строк, проверьте, что количество строк с непустым значением в этом столбце совпадает с общим количеством строк. Если есть несоответствие, миграция не применилась ко всем строкам.
Выполняйте эти проверки с помощью простых count-запросов. Избегайте соединений или агрегаций, которые могут создать излишнюю нагрузку на базу данных.
Следите за логами приложения на предмет ошибок базы данных
Самый важный шаг верификации — проверка, может ли приложение по-прежнему работать с базой данных после миграции. Код приложения, который сейчас выполняется, был написан для старой схемы. Если миграция изменила схему таким образом, что ломает работающий код, в логах приложения появятся ошибки.
Ищите ошибки, упоминающие отсутствующие столбцы, несоответствие типов или неудачные запросы. Эти ошибки означают, что приложение и база данных рассинхронизированы. Команде нужно быстро решить, откатывать ли миграцию или развёртывать исправление кода, соответствующее новой схеме.
Не ждите, пока пользователи сообщат об этих ошибках. Пайплайн должен извлекать логи приложения из системы мониторинга и автоматически сканировать их на предмет ошибок, связанных с базой данных.
Практический чек-лист пост-миграционной проверки
Если вы настраиваете пост-миграционную верификацию впервые, начните с этих проверок в вашем пайплайне:
Следующая блок-схема иллюстрирует рекомендуемую последовательность шагов верификации:
- Статус миграции: завершилась ли она полностью, и на каком этапе остановилась, если произошёл сбой?
- Задержка запросов: находятся ли пять критических запросов всё ещё в приемлемом диапазоне?
- Блокировки: остались ли какие-либо активные блокировки после миграции?
- Количество строк: совпадают ли числа с ожиданиями для миграций, изменяющих данные?
- Ошибки приложения: появились ли новые ошибки, связанные с базой данных, в логах?
Запускайте эти проверки автоматически после каждой миграции. Отправляйте результаты команде в виде отчёта. Если все проверки пройдены, миграцию можно оставить. Если какая-либо проверка не пройдена, у команды есть достаточно информации для принятия следующего решения.
Вывод
Зелёный статус миграции не является гарантией безопасности. Настоящий тест — это то, продолжают ли база данных и приложение хорошо работать вместе после изменения. Пост-миграционная верификация устраняет разрыв между «миграция выполнилась» и «система здорова». Без неё вы развёртываете вслепую и надеетесь на лучшее.