Документация

К списку статей
26. Миграции и обновление контура (без потери данных)

Аудитория: суперадминистратор, инженер эксплуатации. Закрывает вопрос: «как накатываются миграции схемы и как безопасно обновить контур на боевых данных, ничего не потеряв?». Связано: 08 — Эксплуатация и бэкап, 27 — Восстановление.


Как работают миграции сейчас
  • Инициализатор dbinit (app.init_db) на старте: создаёт роль licenziar_app, затем

**apply_migration() применяет ВСЕ backend/migrations/*.sql по порядку имени** (001_…, 002_…, …), затем сидирует демо-данные.

  • Сейф — отдельный инициализатор vault-init (app.init_vault) против `vaultdb` (свой набор

миграций vault-service/migrations/*.sql).

  • Версионирование через `sam.schema_migrations` (версия = имя файла без .sql): применяются

только непринятые миграции; повторный прогон идемпотентен.

Как dbinit применяет миграции (актуально)

init_db.main() теперь:

ensure_role()
apply_migration()             # ВСЕГДА: накатывает только непринятые версии (или baseline)
if not already_seeded():      # сид — только на пустой БД
    seed()

apply_migration():

  • ведёт sam.schema_migrations, накатывает только отсутствующие там версии;
  • baseline: если журнал пуст, а БД уже наполнена (предшествует версионированию) — помечает

все существующие миграции применёнными без повторного прогона (данные/схему не трогает).

✅ Прежняя грабля «already_seeded пропускает миграции» закрыта: на наполненной БД новые NNN_*.sql теперь накатываются простым перезапуском dbinit (применятся только непринятые). Ручной накат (ниже) остаётся как опция для контролируемого окна/диагностики.

Обновление контура с новыми миграциями (боевые данные)

0. Бэкап обеих БД (db и vaultdb) — см. 08 и backup-vault.sh. Без бэкапа не обновлять.

1. Забрать новый код/образы (git pull + docker compose … build).

2. Пересобрать и поднять — миграции накатятся сами:

cd /opt/licenziar
docker compose -f docker-compose.lic.yml --env-file .env.lic up -d --build

dbinit применит только непринятые миграции портала (по sam.schema_migrations) и затем выйдет (сид пропущен — БД наполнена). При изменении схемы Сейфа vault-init отрабатывает аналогично против vaultdb.

2-альт. Ручной накат (контролируемое окно/диагностика) — по-прежнему возможен:

cat backend/migrations/0NN_new.sql \
  | docker compose -f docker-compose.lic.yml --env-file .env.lic exec -T db \
      psql -U postgres -d licenziar -v ON_ERROR_STOP=1

Пишите миграции идемпотентно (IF NOT EXISTS, ADD COLUMN IF NOT EXISTS).

4. Обновить производные объекты при необходимости: REFRESH MATERIALIZED VIEW sam.mv_license_utilization;

5. Проверить (см. чек-лист ниже).


Чистая установка (НЕ обновление) и почему нужен down -v

При первичной раскатке/пересоздании схемы с нуля том должен быть чистым, иначе already_seeded пропустит инициализацию и схема останется старой:

docker compose -f docker-compose.lic.yml --env-file .env.lic down -v   # СБРАСЫВАЕТ тома (потеря данных!)
docker compose -f docker-compose.lic.yml --env-file .env.lic up -d --build
down -v удаляет тома pgdata и vaultdataтолько для чистой установки/стенда, никогда на боевых данных без бэкапа.

Проверка после обновления
  1. GET /api/health{"status":"ok","db":"ok"}.
  2. Новые столбцы/таблицы присутствуют: \d sam.<table> в psql.
  3. Инвариант/метрики целы: GET /api/<tenant>/ops-efficiency.
  4. Сейф отвечает: раскрытие DPO по известному user_id возвращает ФИО.
  5. Тесты бэкенда (pytest backend/tests) на тестовом стенде зелёные.
Грабли
  • `already_seeded` ⇒ авто-миграций на боевой БД нет — накатывайте вручную (шаг 2).
  • Две БД — два набора миграций (портал и Сейф). Не забыть Сейф при изменении его схемы.
  • `ANON_SALT` при обновлении НЕ меняется — иначе рассинхрон хешей (это уже ротация, см. 23).

Связанные: 08 — Эксплуатация и бэкап · 27 — Восстановление двух инстансов · 23 — Ротация соли.