Як планувати міграції бази даних без зупинки сервісу

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

Інженер порівнює стару й нову схеми бази даних перед поетапною міграцією

Один реліз майже ніколи не є однією миттю

Навіть якщо розгортання триває кілька хвилин, у цей час запити обробляють різні версії застосунку. Частина процесів уже використовує новий код, інші завершують старі задачі, а фонові працівники можуть оновлюватися окремо. Міграція, яка одночасно перейменовує колонку й очікує нову структуру, створює момент, коли одна з версій неминуче зламається. Безпечніше сприймати зміну схеми як послідовність сумісних станів. Спочатку база має прийняти обидва формати, потім новий код починає записувати потрібні дані, далі команда переносить історичні записи й лише після перевірки видаляє стару структуру. Кожен етап є окремим релізом із власними метриками та можливістю зупинитися. Такий підхід повільніший за одну велику команду, але значно зменшує радіус помилки.

Розширення має передувати видаленню

Практичний шаблон часто називають expand and contract. На етапі розширення команда додає нову колонку, таблицю або зв’язок, не змінюючи поведінку старого коду. Новий застосунок може певний час читати старе значення й паралельно заповнювати нове. Коли накопичено достатньо спостережень, читання перемикають на нову структуру, а стару залишають як запасний шлях. Лише після завершення переходу настає етап скорочення: непотрібні поля, індекси й тимчасову логіку видаляють. Важливо не розтягувати цей стан безмежно. Подвійний запис збільшує складність, а забута тимчасова колонка швидко стає постійною залежністю. Для кожного етапу потрібні власник, дата перевірки та чітка умова завершення.

Індекси й обмеження потребують окремого плану

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

Перенесення даних не повинно конкурувати з користувачами

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

Черги й фонові задачі продовжують жити за старим контрактом

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

Відкат коду не завжди повертає старі дані

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

Стан міграції повинен бути видимим

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

Коментарі