Розробка міграцій бази даних веб-застосунку

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

Розробка та обслуговування будь-яких видів сайтів:

Інформаційні сайти або веб-програми
Сайти візитки, landing page, корпоративні сайти, онлайн каталоги, квіз, промо-сайти, блоги, ресурси новин, інформаційні портали, форуми, агрегатори
Сайти або веб-програми електронної комерції
Інтернет-магазини, B2B-портали, маркетплейси, онлайн-обмінники, кешбек-сайти, біржі, дропшиппінг-платформи, парсери товарів
Веб-програми для управління бізнес-процесами
CRM-системи, ERP-системи, корпоративні портали, системи управління виробництвом, парсери інформації
Сайти або веб-програми електронних послуг
Дошки оголошень, онлайн-школи, онлайн-кінотеатри, конструктори сайтів, портали надання електронних послуг, відеохостинги, тематичні портали

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

Пропоновані послуги
Показано 1 з 1 послугУсі 2065 послуг
Розробка міграцій бази даних веб-застосунку
Середня
від 1 робочого дня до 3 робочих днів
Часті питання

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

Етапи розробки

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

  • image_website-b2b-advance_0.png
    Розробка сайту компанії B2B ADVANCE
    1262
  • image_web-applications_feedme_466_0.webp
    Розробка веб-додатків для компанії FEEDME
    1171
  • image_websites_belfingroup_462_0.webp
    Розробка веб-сайту для компанії БЕЛФІНГРУП
    874
  • image_ecommerce_furnoro_435_0.webp
    Розробка інтернет магазину для компанії FURNORO
    1094
  • image_crm_enviok_479_0.webp
    Розробка веб-додатків для компанії Enviok
    831
  • image_bitrix-bitrix-24-1c_fixper_448_0.png
    Розробка веб-сайту для компанії ФІКСПЕР
    851

Розробка міграцій бази даних для веб-додатків

Міграції — керований спосіб змінювати схему БД разом із кодом. Без них зміни схеми розгортаються вручну, втрачаються в Slack або вызивают інциденти в продакшені.

Інструменти

Вибір залежить від вашого стеку:

Інструмент Стек Формат
Flyway Java, будь-який SQL
Liquibase Java, будь-який XML/YAML/SQL
Alembic Python/SQLAlchemy Python
golang-migrate Go, будь-який SQL
Laravel Migrations PHP/Laravel PHP
Rails Migrations Ruby/Rails Ruby
Knex Node.js JS
Prisma Migrate Node.js/TypeScript Prisma schema

Універсальний варіант — golang-migrate або Flyway з чистим SQL: не залежать від ORM, працюють з CI без додатку, міграції читаються без знання специфіки ORM.

Принципи написання міграцій

Кожна міграція — атомарна і оборотна. Якщо не можна написати коректний down, це сигнал, що міграція робить занадто багато.

Міграції в production не редагуються. Якщо помилка застосована — напишіть нову міграцію.

Немає data migrations в schema migrations. Перенесення даних — окремий скрипт.

Приклад із golang-migrate

migrate create -ext sql -dir db/migrations -seq add_search_vector_to_products

Створює два файли: 000003_add_search_vector_to_products.up.sql та ...down.sql.

-- 000003_add_search_vector_to_products.up.sql

BEGIN;

ALTER TABLE products
    ADD COLUMN IF NOT EXISTS search_vector TSVECTOR;

UPDATE products
SET search_vector = to_tsvector('russian', coalesce(title, '') || ' ' || coalesce(description, ''));

CREATE INDEX CONCURRENTLY idx_products_search ON products USING GIN (search_vector);

CREATE OR REPLACE FUNCTION products_search_vector_update() RETURNS TRIGGER AS $$
BEGIN
    NEW.search_vector := to_tsvector('russian',
        coalesce(NEW.title, '') || ' ' || coalesce(NEW.description, '')
    );
    RETURN NEW;
END;
$$ LANGUAGE plpgsql;

CREATE TRIGGER products_search_vector_trigger
    BEFORE INSERT OR UPDATE ON products
    FOR EACH ROW EXECUTE FUNCTION products_search_vector_update();

COMMIT;
-- 000003_add_search_vector_to_products.down.sql

BEGIN;
DROP TRIGGER IF EXISTS products_search_vector_trigger ON products;
DROP FUNCTION IF EXISTS products_search_vector_update();
DROP INDEX IF EXISTS idx_products_search;
ALTER TABLE products DROP COLUMN IF EXISTS search_vector;
COMMIT;

CREATE INDEX CONCURRENTLY не можна виконувати всередині транзакції. Для таких міграцій обертаємо в окремий крок без BEGIN/COMMIT, або використовуємо Flyway з executeInTransaction = false.

Міграції без простоїв

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

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

Додавання колонки:

-- Безпечно: nullable без DEFAULT або з константою
ALTER TABLE users ADD COLUMN phone VARCHAR(20);
-- Небезпечно в старих PostgreSQL: NOT NULL з DEFAULT — переписування таблиці
-- Безпечно в PostgreSQL 11+: NOT NULL з DEFAULT константою (без переписування)
ALTER TABLE users ADD COLUMN is_verified BOOLEAN NOT NULL DEFAULT false;

Перейменування колонки — завжди в 3 етапи:

Deploy 1: додати нову колонку, код пише в обидві
Deploy 2: перенести дані, код читає з нової
Deploy 3: видалити старку колонку

Зміна типу колонки:

-- PostgreSQL 12+: миттєвий для varchar(n) -> varchar(m) коли m > n
-- переписування таблиці для більшості інших змін типу

-- Безпечний шлях: додати нову, скопіювати, перемкнути
ALTER TABLE products ADD COLUMN price_cents BIGINT;
UPDATE products SET price_cents = (price * 100)::BIGINT;
-- наступний deploy коду: читаємо price_cents
-- наступна міграція: DROP COLUMN price

Видалення колонки:

-- Спочатку код перестає читати/писати колонку (deploy)
-- Потім міграція
ALTER TABLE products DROP COLUMN old_field;

Версіонування та іменування

Добрий формат імені: {timestamp}_{verb}_{object}_{detail}.

20240315_001_create_users.sql
20240315_002_add_email_index_to_users.sql
20240320_001_add_status_to_products.sql
20240401_001_create_orders.sql

Версії на основі timestamp (як у Flyway) краще за sequence-based (Alembic --autogenerate) при паралельній роботі декількох розробників: немає конфліктів версій.

CI/CD інтеграція

# .github/workflows/deploy.yml (фрагмент)
- name: Run migrations
  run: |
    migrate -path db/migrations \
            -database "$DATABASE_URL" \
            -verbose up
  env:
    DATABASE_URL: ${{ secrets.DATABASE_URL }}

- name: Deploy application
  run: ./deploy.sh

Міграції застосовуються до розгортання нового коду. Откат: migrate down N — откатити N останніх міграцій.

Flyway для Java/будь-якого стеку

<!-- pom.xml -->
<plugin>
    <groupId>org.flywaydb</groupId>
    <artifactId>flyway-maven-plugin</artifactId>
    <configuration>
        <url>${DB_URL}</url>
        <user>${DB_USER}</user>
        <password>${DB_PASSWORD}</password>
        <locations>classpath:db/migration</locations>
        <outOfOrder>false</outOfOrder>
        <validateOnMigrate>true</validateOnMigrate>
    </configuration>
</plugin>
mvn flyway:migrate
mvn flyway:info      # статус усіх міграцій
mvn flyway:validate  # перевірити контрольні суми

Flyway зберігає контрольну суму кожної міграції в таблиці flyway_schema_history. Якщо файл змінився після застосування — validate видасть помилку.

Графіки

Налаштування інфраструктури міграцій (інструмент, іменування, CI-крок, процедура откату) для нового проекту: половина дня. Написання набору початкових міграцій для існуючої схеми (reverse engineering): 1 день.