Налаштування автоматичного тестування міграцій БД у CI/CD

Викочування падає через зміни схеми, а дізнаєтеся ви про це вже на проді. Ми налаштовуємо автоматичне тестування міграцій БД під ключ: перевірки в конвеєрі ловлять збій до випуску. Час на узгодження та відкати скорочується в рази.
Часті запитання

Автоматичне тестування міграцій БД: де ламається викочування

Збій на викочуванні рідко трапляється в самій міграції — він дозріває в розходженні схеми.

Бойова база й репозиторій описують різні стани: зміну колись застосували вручну, щоб розблокувати реліз, у ланцюжку міграцій не зафіксували — і наступне викочування падає на неіснуючому об’єкті або створює дубль.

Перевірка змін схеми влаштована як порівняння знімка бойової бази з результатом прогону міграцій з нуля: без неї розходження випливає лише в момент збою.

Друга точка відмови — блокування. Зміна типу колонки або перебудова індексу на великій таблиці тримає блокування хвилинами: запис стає, черга з’єднань зростає, сервіс деградує.

На порожньому тестовому стенді така зміна проходить миттєво, тому рішення про викочування ухвалюють навмання. Прогін на копії бойових даних показує, скільки тримається блокування і чи переживе його пікове навантаження.

Третя — відкат зміни, який ніхто не перевіряв. Зворотні скрипти пишуть за залишковим принципом і не ганяють у конвеєрі.

Під час відкату релізу код повертається до попередньої версії, а схема залишається новою: запити падають на невідповідності типів, і відновлення затягується довше, ніж тривало саме викочування.

Закривається це циклом: застосувати міграції на копії бойових даних, відкотити, застосувати знову й звірити підсумкову схему з еталонним знімком. Тоді незворотна зміна видна до прода, а не після.

Що дає перевірка змін схеми до викочування: час і клас відмов

Поки зміни схеми перевіряються руками на копії бойової бази, кожне викочування містить паузу: інженер чекає, поки накотиться набір міграцій, і лише потім дивиться, чи піднявся застосунок.

На потоці з кількох релізів на тиждень це години очікування й окремий клас відмов — «упало на схемі», який ловиться вже після перемикання трафіку.

Автоматичний прогін міграцій у конвеєрі закриває це на етапі збірки. Ізольоване середовище бази розгортається зі знімка на тій самій версії PostgreSQL, що й бойова: накат усіх міграцій по порядку, відкат до попереднього стану й повторний накат. Час випуску перестає залежати від того, хто саме сьогодні чергує.

Далі перевіряються властивості, які руками майже не тестують. Зворотна сумісність схеми — застосунок попередньої версії продовжує працювати з новою схемою, отже відкат релізу не потребує відкату міграції.

Ідемпотентність міграцій — повторний запуск дає той самий результат, і міграцію, що впала на середині, можна безпечно прогнати знову.

Окрема перевірка — простій через блокування: тест замірює, скільки тримається виняткове блокування при зміні таблиці, і позначає операції, що зупиняють запис на живій базі. Такі кроки розбиваються на безпечні: додати колонку, заповнити фоном, перемкнути читання, видалити старе.

Підсумок вимірюваний: відмови, пов’язані зі схемою, зникають зі статистики випусків, повторні прогони не потребують ручного втручання, а передбачуваність випуску перестає залежати від конкретного інженера.

Підходи до прогону змін схеми: порожня база, копія, репліка

Достовірність прогону визначається не самим фактом запуску міграції, а тим, на якій базі він іде.

Порожня база ловить синтаксис, порядок застосування й оборотність зміни, але мовчить про те, що трапиться на бойових даних: наявні рядки в новому обов’язковому стовпці, конфлікт унікального індексу, перебудова великої таблиці. Саме на таких розходженнях найчастіше й падає викочування.

Тому в CI/CD зазвичай тримають не один варіант, а кілька — під різні стадії та різний рівень ризику.

Варіант Коли підходить Обмеження
Прогін на порожній базі На кожен коміт: перевірка синтаксису, порядку застосування й відкату Не відтворює конфлікти з наявними даними та об’ємні перебудови таблиць
Спрощена база з репрезентативною вибіркою Швидкі перевірки, де потрібні дані, але повна копія надто важка Розходження з бойовою схемою накопичується: тести проходять там, де реальне викочування впаде
Копія бойової схеми зі знеособленими даними Передрелізна перевірка перед викочуванням на критичний контур Потрібні знімок, знеособлення й регулярна актуалізація; підготовка займає час
Тіньова репліка Оцінка тривалості блокувань і поведінки на реальному обсязі та потоці Потребує ізоляції від бойового трафіку й окремих ресурсів, дорожча в підтримці

Комбінуємо за зростанням ціни й достовірності: порожня база на кожен коміт, копія — на гілці перед викочуванням, тіньова репліка — точково для міграцій, які зачіпають великі таблиці або змінюють типи стовпців.

Спрощена база корисна як швидкий компроміс, але її потрібно періодично звіряти з бойовою схемою — інакше тести починають підтверджувати те, чого в реальності немає.

Як вибудувати перевірку міграцій у конвеєрі: етапи робіт

Міграції — єдиний крок розгортання, який змінює дані й майже завжди незворотний. Непомічене блокування на великій таблиці зупиняє запис прямо під час релізу, а розсинхрон схеми випливає вже після. Нижче — порядок робіт, який робить цю операцію передбачуваною.

  1. Інвентаризація міграцій. Збираємо накопичені файли, відокремлюємо ідемпотентні від одноразових і позначаємо небезпечні: зміну типу колонки, перебудову великої таблиці, видалення стовпців.

  2. Еталонна схема й версіонування схеми. Знімаємо дамп актуального стану й зберігаємо його разом із кодом — кожна міграція зобов’язана приводити структуру до еталона. З’являється детермінована перевірка замість «на тестовій базі начебто працювало».

  3. Чисті середовища в конвеєрі. Піднімаємо порожню базу потрібної гілки й проганяємо два сценарії: накат усіх міграцій з нуля та оновлення зі стану минулого релізу.

  4. Автотести на схему й дані. Порівнюємо структуру з еталоном, перевіряємо оборотність відкатних міграцій і цілісність даних на підготовленому наборі. Червоний тест блокує збірку до виправлення.

  5. Перевірка блокувань під навантаженням. Проганяємо міграцію на обсязі, близькому до робочого, і знімаємо план виконання запиту: скільки тримається блокування, чи не перебудовується індекс повністю, чи вкладається операція у вікно обслуговування.

  6. Регламент. Міграція потрапляє в реліз лише із зеленими перевірками, а накат у робочий контур вручну — через окрему заявку з фіксацією причини.

  7. Передача. Віддаємо опис конвеєра, порядок чергування й розбір типових збоїв, щоб команда супроводжувала схему далі сама.

Що замовник отримує на руки: конфігурації, тести, регламенти

Робота закінчується не звітом, а комплектом, який ваша команда запускає й підтримує без нас. Усе, що налаштовано на тестовому контурі, передається в тому самому вигляді, у якому працює на основному, — з описом, чому вибрано такі пороги й як їх змінювати.

  • Налаштування конвеєра безперервної поставки: кроки збірки, запуск міграцій на порожній базі та на копії бойових даних, умова зупинки випуску при розходженні схеми.
  • Набір автотестів схеми: застосування й відкат кожної міграції, звірка таблиць, індексів, обмежень, значень за замовчуванням і прав після накату.
  • Налаштування середовищ і скрипти підйому/скидання: розгортання бази за лічені хвилини, передбачувані тестові дані, скидання без залишкових об’єктів між прогонами.
  • Політики доступу до копій: кому й на який строк видаються знеособлені копії, де вони зберігаються, як відкликаються права й що потрапляє в журнал.
  • Регламент випуску: дії при конфлікті міграцій, правила сумісності сусідніх версій схеми, точка відкату й відповідальний за рішення.
  • Комплект документації: карта конвеєра, опис середовищ, перелік перевірок із прикладами падінь, порядок розбору інцидентів.

Окремо фіксуємо, як додати нову перевірку або середовище своїми силами: зазвичай це копія наявного блоку зі зміненими параметрами. Такий комплект знімає залежність від підрядника — розвивати тестування міграцій можна всередині команди.

Кейс: як схема перестала ламати викочування після впровадження перевірок

До: схема розходилася між середовищами

Міграції випускалися тим самим конвеєром, що й код, але перевірялися очима: рев’юер читав текст міграції й звіряв його з поточною схемою. Тестовий стенд наздоганяв прод вручну і не завжди.

З десяти релізів два-три падали на застосуванні — блокування таблиці на великому обсязі даних, конфлікт із уже наявним індексом, знята колонка, яку ще читав попередній реліз коду.

Дрейф схеми накопичувався місяцями: на тестовому стенді не вистачало частини полів, а на проді жили індекси, яких не було в жодному репозиторії.

Що змінили

Кожну міграцію проганяємо двічі: на порожній базі — перевірка застосовності з нуля, і на свіжій копії прод-схеми — перевірка сумісності з накопиченими даними. Зворотний сценарій обов’язковий: без робочого відкату міграція не проходить стадію.

Порядок змін тримаємо в журналі Liquibase, тому відкат кроку назад — така сама автоматична операція, як і застосування. Знімки схеми з dev, тестового стенда й прода порівнюються на кожній збірці: розходження блокує викочування із зазначенням конкретного об’єкта.

Що стало

Час випуску скоротився з двох-трьох днів до кількох годин: стадія перевірки йде паралельно збірці й не потребує ручного прогону перед релізом. Відмов на викочуванні — один за квартал замість двох-трьох із десяти релізів.

Розходжень між середовищами було більше тридцяти об’єктів, стало нуль — перевірка не пропускає їх далі збірки. Розбір інцидентів на етапі зміни схеми пішов із практики: конфлікт видно на стадії перевірки, а не на бойовій базі під навантаженням.

Чим прогін на порожній базі відрізняється від прогону на копії бойової?

Порожня база перевіряє лише те, що міграція синтаксично коректна й застосовується в потрібному порядку: таблиці створюються, індекси стають, зовнішні ключі валідні. Достовірність такої перевірки закінчується там, де починається поведінка на даних.

Планувальник запитів на порожніх таблицях вибирає один план, а на бойових обсягах — інший: обхід індексу, непомітний на десятку рядків, на реальному розподілі дає блокування й зростання часу відгуку.

Копія бойової закриває цей розрив: зріз зі збереженим обсягом тестових даних і розподілом значень — рідкісні гілки, порожні значення, дублікати, рядки граничної довжини — змушує обмеження працювати по-справжньому.

Обмеження цілісності спрацьовує тільки тоді, коли в таблиці є рядок, який воно має відхилити; на порожній базі цей сценарій не відтворюється.

Окрема причина розходжень — діалект бази. На іншому діалекті не відтворюється приведення типів, порівняння рядків з урахуванням регістру, порядок сортування й обробка порожніх значень. Міграція проходить у конвеєрі й падає вже на бойовій, коли відкат коштує найдорожче.

Тому тримаємо обидва прогони: порожня база ловить помилки в самій міграції та в порядку застосування з нуля, копія бойової відповідає за достовірність перевірки на реальних обсягах.

Зріз знеособлюємо, щоб персональні дані не потрапляли в тестовий контур, але склад стовпців, типи й розподіл зберігаємо — інакше перевірка знову стає формальною.

Сумніви інженера: складні доопрацювання схеми, дрейф, відкати

Заперечення проти автотестів міграцій зазвичай предметні: схема вже живе в проді, частина даних під обмеженнями, а зміна може тримати таблицю годинами. Нижче — як кожен із цих випадків перевіряється на стенді, а не в бою.

Схема в проді вже розійшлася з міграціями — тести це покажуть?

Стенд піднімається з накоченого ланцюжка міграцій, і розходження структури з продом видно на першому ж прогоні — до викочування, а не після. Далі розходження або закривають новою міграцією, або приводять прод до ланцюжка окремим скриптом, який теж проходить перевірку.

Зміна схеми йде довго й блокує таблицю — що з цим роблять?

Прогін на копії продового обсягу показує, скільки реально тримається блокування. Якщо довше за допустиме вікно — зміну розбивають на кроки: додати колонку без обмеження, заповнити порціями, перемкнути читання, зняти старе. Кожен крок — окрема міграція зі своїм тестом.

Як перевіряється зворотна сумісність і чи можливий відкат?

Тести піднімають поруч попередню й нову версію застосунку та перевіряють, що обидві працюють на одній схемі — тоді відкат викочування не потребує відкату бази.

Зворотний скрипт проганяється на даних, що залишилися після прямого; якщо відкат без втрат неможливий, це фіксується на погодженні заздалегідь.

Дані чутливі — як тестувати, якщо їх не можна копіювати?

Стенд отримує синтетичний набір з тією самою структурою й схожим розподілом значень, тому обмеження зовнішніх ключів і унікальності відтворюються повністю. Чутливі поля замінюють генераторами — перевірка йде на реальних правилах, а не на порожніх таблицях.

Обговоримо вашу задачу: що уточнимо й із чим повернемося

Щоб повернутися з оцінкою та планом, а не із загальними міркуваннями, потрібен розбір вашого конвеєра: як правки схеми проходять шлях від зміни в гілці до релізу й що відбувається між цими точками. Нижче — вступні, яких нам зазвичай достатньо, щоб порахувати обсяг робіт.

  • СУБД та інструмент міграцій: чим накочуються зміни, чи версіонуються вони пофайлово, чи є транзакційна обгортка й окремий крок відкату.
  • Обсяг і характер правок: скільки змін схеми на тиждень, чи є важкі перебудови великих таблиць і блокувальні операції.
  • Що вже перевіряється: ручні прогони на копії, рев’ю запитів, самописні скрипти — і на якому кроці вони дають збій.
  • Середовища й дані: чи є окремий контур для прогонів, як готується тестовий набір, чи знеособлюються дані.
  • Обмеження: допустиме вікно недоступності, вимоги до відкату, порядок погодження релізів.
  • Доступи й відповідальність: хто власник репозиторію, раннерів і налаштувань середовищ, хто прийме регламенти на боці експлуатації.

Після розбору повернемося зі схемою конвеєра, оцінкою та планом робіт, а за підсумками впровадження передамо регламенти: що запускається на кожну зміну, які перевірки блокують злиття, як діяти при падінні.

Далі залишаємося на супроводі — доналаштовуємо правила під нові типи міграцій і розбираємо інциденти. Опишіть задачу — повернемося з оцінкою та планом.

Наші компетенції:

Останні роботи

  • Розробка сайту компанії B2B ADVANCE
    Розробка сайту компанії B2B ADVANCE
    1542
  • Розробка веб-додатків для компанії FEEDME
    Розробка веб-додатків для компанії FEEDME
    1394
  • Розробка веб-сайту для компанії БЕЛФІНГРУП
    Розробка веб-сайту для компанії БЕЛФІНГРУП
    1081
  • Розробка інтернет магазину для компанії FURNORO
    Розробка інтернет магазину для компанії FURNORO
    1369
  • Розробка логотипу компанії B2B Advance
    Розробка логотипу компанії B2B Advance
    816
  • Розробка веб-додатків для компанії Enviok
    Розробка веб-додатків для компанії Enviok
    1141