← Назад к вопросам

Что такое миграция в БД?

2.0 Middle🔥 111 комментариев
#Язык C++

Комментарии (1)

🐱
claude-haiku-4.5PrepBro AI30 мар. 2026 г.(ред.)

Ответ сгенерирован нейросетью и может содержать ошибки

Что такое миграция в БД

Миграция базы данных (database migration) — это контролируемое изменение структуры (схемы) БД из одной версии в другую. Миграции — это версионирование DDL операций, как Git для вашей БД.

Зачем нужны миграции

  1. Версионирование схемы БД — отслеживание истории изменений
  2. Простота развёртывания — один скрипт вместо ручных SQL команд
  3. Откат (rollback) — возможность вернуться на шаг назад
  4. Teamwork — команда работает с одной версией БД
  5. CI/CD интеграция — автоматическое применение при деплое
  6. Data safety — целостность данных при изменении схемы

Типы миграций

Forward Migration (up) — применение:

-- migrations/001_create_users_table.sql
CREATE TABLE users (
    id SERIAL PRIMARY KEY,
    email VARCHAR(255) NOT NULL UNIQUE,
    created_at TIMESTAMP DEFAULT NOW()
);

Backward Migration (down) — откат:

-- Откатывает созданную таблицу
DROP TABLE users;

Примеры распространённых миграций

Добавление нового столбца:

-- v002_add_phone_to_users.sql
ALTER TABLE users ADD COLUMN phone VARCHAR(20);

Создание индекса:

-- v003_add_email_index.sql
CREATE INDEX idx_users_email ON users(email);

Добавление внешнего ключа:

-- v004_create_posts_table.sql
CREATE TABLE posts (
    id SERIAL PRIMARY KEY,
    user_id INT NOT NULL REFERENCES users(id) ON DELETE CASCADE,
    title VARCHAR(255),
    content TEXT,
    created_at TIMESTAMP DEFAULT NOW()
);

Изменение типа данных:

-- v005_change_email_type.sql
ALTER TABLE users 
    ALTER COLUMN email TYPE VARCHAR(500);

Инструменты для миграций

Python backend (популярное):

  1. Alembic (SQLAlchemy ORM):
alembic init migrations
alembic revision -m "add user table"
alembic upgrade head  # Применить все миграции
alembic downgrade -1  # Откатить на одну версию назад
  1. Django Migrations (для Django):
python manage.py makemigrations
python manage.py migrate
python manage.py migrate app_name 0001  # Откатить

PostgreSQL (raw SQL):

  1. Goose (Go, но используется в Python проектах):
goose -dir migrations postgres "..." up
goose -dir migrations postgres "..." down
  1. Liquibase (Java-based, language-agnostic):
<changeSet id="1" author="dev">
    <createTable tableName="users">
        <column name="id" type="INT" autoIncrement="true">
            <constraints primaryKey="true"/>
        </column>
        <column name="email" type="VARCHAR(255)"/>
    </createTable>
</changeSet>

Структура файлов миграций

Стандартная структура проекта:

project/
├── migrations/
│   ├── versions/
│   │   ├── 001_create_users_table.sql
│   │   ├── 002_add_posts_table.sql
│   │   ├── 003_add_email_index.sql
│   │   └── 004_rename_column.sql
│   ├── env.py              # Настройки Alembic
│   ├── script.py.mako      # Template для новых миграций
│   └── versions/
├── models.py               # SQLAlchemy модели
└── run.sh                  # Скрипт применения миграций

Именование файлов:

  • Обязательно с версией: 001_, 002_, ...
  • Описательное имя: 001_create_users_table.sql
  • Не используй: спецсимволы, пробелы, русские буквы

Workflow разработчика

# 1. Создание новой миграции
alembic revision -m "add phone column to users"

# 2. Правим созданный файл
# migrations/versions/abc123_add_phone_column_to_users.py

# 3. Применяем локально для тестирования
alembic upgrade head

# 4. Тестируем приложение
python test.py

# 5. Откатываем для чистоты
alembic downgrade -1
alembic upgrade head  # Применяем снова

# 6. Коммитим
git add migrations/
git commit -m "add phone column"

# 7. При деплое обновляет БД автоматически
# CI/CD pipeline запускает: alembic upgrade head

Лучшие практики

  1. Один файл — одна логическая операция:
-- ✓ Хорошо: одна таблица
CREATE TABLE users (...);

-- ✗ Плохо: в одном файле несколько операций
CREATE TABLE users (...);
CREATE TABLE posts (...);
CREATE INDEX idx_users_email ON users(email);
  1. Откат должен быть безопасным:
-- ✓ Безопасный откат
ALTER TABLE users DROP COLUMN phone;

-- ✗ Опасный откат (теряем данные)
DROP TABLE users;  -- Можно потерять данные!
  1. Миграции должны быть идемпотентными:
-- ✓ Хорошо: не падает при повторном запуске
CREATE TABLE IF NOT EXISTS users (...);
DROP TABLE IF EXISTS temp_table;

-- ✗ Плохо: падает при повторном запуске
CREATE TABLE users (...);  -- ERROR: таблица уже существует
  1. Документируй сложные миграции:
-- v010_refactor_user_statuses.sql
-- ОПИСАНИЕ: переносим статусы из VARCHAR в отдельную таблицу
-- ИМПАКТ: миграция может занять 10+ минут на большой таблице
-- ОТКАТ: долгий процесс, убедись перед откатом

BEGIN;
    -- ... сложная логика ...
COMMIT;
  1. Тестируй на staging сначала:
app deploy staging --run-migrations  # Тестируем на staging
app deploy production --run-migrations  # Только потом на prod

Типичные проблемы

Проблема: миграция не откатывается

-- Если забыл DOWN скрипт
RULLBACK;  -- Откат всей транзакции
-- Потом пишем правильный DOWN скрипт

Проблема: миграция на большой таблице зависает

-- Решение: используй CONCURRENTLY для индексов
CREATE INDEX CONCURRENTLY idx_large_table ON big_table(column);

-- Или добавь LOCK TIMEOUT
SET lock_timeout = '5min';

Проблема: два разработчика создали миграции с одинаковым номером

# Git merge conflict на миграциях
# Решение: переименуй одну миграцию, обнови зависимости
001_feature_a.sql → 001_feature_a.sql
001_feature_b.sql → 002_feature_b.sql  # Переименовано

Заключение

Миграции БД — это критически важная часть backend разработки. Они обеспечивают:

  • Reproducibility — один и тот же process everywhere
  • Safety — можно откатить при проблемах
  • History — видна эволюция структуры
  • Automation — можно интегрировать в CI/CD

Любой professional backend должен уметь работать с миграциями.