Миграции базы данных

Миграции базы данных

Проект использует golang-migrate для управления схемой базы данных состояний (StateStorage).

Обзор

Миграции применяются автоматически при старте приложения (если auto_migrate: true) или могут быть применены вручную. Все миграции находятся в папке migrations/ и следуют стандартному формату golang-migrate.

Формат миграций

Миграции используют формат:

  • 000001_<name>.up.sql — применение миграции
  • 000001_<name>.down.sql — откат миграции

Текущие миграции

  1. 000001_create_worker_progress — создание таблицы worker_progress
  2. 000002_create_meta_learning_state — создание таблицы meta_learning_state

Автоматическое применение

При включенном auto_migrate: true в конфигурации StateStorage:

state_storage:
  auto_migrate: true  # Миграции применяются автоматически при старте

Миграции применяются автоматически при инициализации StateStorage:

stateStorage, err := storage.NewStateStorage(ctx, log, &cfg.StateStorage)
// Миграции применяются автоматически

Ручное управление миграциями

Установка golang-migrate

# macOS
brew install golang-migrate

# Linux
curl -L https://github.com/golang-migrate/migrate/releases/download/v4.19.0/migrate.linux-amd64.tar.gz | tar xvz
sudo mv migrate /usr/local/bin/migrate

# Windows
choco install golang-migrate

Применение миграций

# Применить все миграции
migrate -path migrations \
  -database "postgres://user:password@localhost:5432/ml_states?sslmode=disable" \
  up

# Применить N миграций
migrate -path migrations \
  -database "postgres://user:password@localhost:5432/ml_states?sslmode=disable" \
  up N

# Откатить последнюю миграцию
migrate -path migrations \
  -database "postgres://user:password@localhost:5432/ml_states?sslmode=disable" \
  down 1

# Откатить все миграции
migrate -path migrations \
  -database "postgres://user:password@localhost:5432/ml_states?sslmode=disable" \
  down -all

Проверка версии

# Текущая версия миграций
migrate -path migrations \
  -database "postgres://user:password@localhost:5432/ml_states?sslmode=disable" \
  version

# Принудительно установить версию (осторожно!)
migrate -path migrations \
  -database "postgres://user:password@localhost:5432/ml_states?sslmode=disable" \
  force VERSION

Использование схем

Если используется отдельная схема:

migrate -path migrations \
  -database "postgres://user:password@localhost:5432/ml_states?sslmode=disable&search_path=ml_states" \
  up

Структура миграций

000001_create_worker_progress

Создает таблицу worker_progress для отслеживания статуса обработки заданий.

Основные поля:

  • message_id (UUID, PRIMARY KEY) — уникальный идентификатор сообщения
  • status (VARCHAR) — статус: pending, processing, completed, failed
  • worker_id (VARCHAR) — идентификатор воркера
  • progress_percent (DECIMAL) — процент выполнения
  • current_generation (INT) — текущее поколение GA
  • intermediate_results (JSONB) — промежуточные результаты

Индексы:

  • idx_worker_progress_status — по статусу и времени обновления
  • idx_worker_progress_worker — по воркеру и статусу
  • idx_worker_progress_updated — по времени обновления

000002_create_meta_learning_state

Создает таблицу meta_learning_state для хранения состояний Meta Learning, Transfer Learning и GA checkpoints.

Основные поля:

  • id (UUID, PRIMARY KEY) — уникальный идентификатор
  • test_id (VARCHAR) — ID конкретного теста
  • message_id (UUID) — связь с worker_progress
  • state_type (VARCHAR) — тип: meta_learning, transfer_learning, genetic_algorithm
  • knowledge_key (VARCHAR) — составной ключ для глобальных знаний
  • is_global (BOOLEAN) — флаг глобального состояния
  • state_data (JSONB) — полное состояние
  • generation (INT) — текущее поколение GA
  • checkpoint_type (VARCHAR) — тип checkpoint
  • expires_at (TIMESTAMP) — время истечения
  • version (INT) — версия для оптимистичных блокировок

Индексы:

  • idx_meta_learning_knowledge_key — для поиска глобальных знаний
  • idx_meta_learning_test_id — для поиска checkpoint’ов
  • idx_meta_learning_message_id — для поиска по message_id
  • idx_meta_learning_exchange_pair_model — по комбинации полей
  • idx_meta_learning_expires — для очистки истекших состояний
  • idx_meta_learning_global_unique — уникальный индекс для глобальных знаний

Создание новых миграций

Через golang-migrate CLI

# Создать новую миграцию
migrate create -ext sql -dir migrations -seq add_new_feature

# Это создаст:
# migrations/000003_add_new_feature.up.sql
# migrations/000003_add_new_feature.down.sql

Вручную

  1. Создайте файлы 00000N_<name>.up.sql и 00000N_<name>.down.sql
  2. Реализуйте логику применения и отката
  3. Протестируйте миграции на тестовой БД

Пример новой миграции

000003_add_index.up.sql:

CREATE INDEX IF NOT EXISTS idx_meta_learning_created 
ON meta_learning_state(created_at);

000003_add_index.down.sql:

DROP INDEX IF EXISTS idx_meta_learning_created;

Проверка применения миграций

Через SQL

-- Проверка версии миграций
SELECT version, dirty 
FROM schema_migrations;

-- Проверка существования таблиц
SELECT table_name 
FROM information_schema.tables 
WHERE table_schema = 'public' 
  AND table_name IN ('worker_progress', 'meta_learning_state');

-- Проверка структуры таблицы
\d worker_progress
\d meta_learning_state

Через приложение

При старте приложения логируется информация о применении миграций:

✅ Миграции состояний применены

Откат миграций

Через golang-migrate

# Откатить последнюю миграцию
migrate -path migrations \
  -database "postgres://user:password@localhost:5432/ml_states?sslmode=disable" \
  down 1

# Откатить все миграции
migrate -path migrations \
  -database "postgres://user:password@localhost:5432/ml_states?sslmode=disable" \
  down -all

Внимание: Откат удалит данные из таблиц!

Troubleshooting

Миграции не применяются

  1. Проверьте путь к миграциям в конфигурации
  2. Проверьте права доступа к БД
  3. Проверьте логи приложения при старте
  4. Проверьте версию миграций: migrate version

Ошибка “dirty database version”

Если миграция прервалась, база может остаться в “dirty” состоянии:

# Принудительно установить версию
migrate -path migrations \
  -database "postgres://user:password@localhost:5432/ml_states?sslmode=disable" \
  force VERSION

Конфликты при конкурентном доступе

Миграции применяются атомарно. Если несколько экземпляров приложения запускаются одновременно, только один применит миграции.

Рекомендация: Применяйте миграции вручную перед запуском приложения в production.

Рекомендации

  1. Development: Используйте auto_migrate: true для удобства
  2. Production: Применяйте миграции вручную перед деплоем
  3. CI/CD: Добавьте проверку миграций в pipeline
  4. Backup: Делайте backup БД перед применением миграций
  5. Testing: Тестируйте миграции на тестовой БД перед production

Интеграция с CI/CD

Пример для GitHub Actions

- name: Run migrations
  run: |
    migrate -path migrations \
      -database "${{ secrets.DATABASE_URL }}?sslmode=disable" \
      up

Пример для GitLab CI

migrate:
  script:
    - migrate -path migrations -database "$DATABASE_URL?sslmode=disable" up

Дополнительные ресурсы