Mnesia migrations with global lock on startup. Refs EventHub/EventHubBack#24
This commit is contained in:
+43
-23
@@ -1,23 +1,43 @@
|
||||
# Миграции схемы данных EventHub
|
||||
|
||||
## Применение миграций
|
||||
При старте приложения автоматически выполняются все неприменённые миграции.
|
||||
Для ручного запуска можно вызвать:
|
||||
migration_engine:apply_pending().
|
||||
|
||||
## Создание новой миграции
|
||||
1. Создайте файл в `priv/migrations/` с именем вида `YYYYMMDDHHMMSS_описание.erl`.
|
||||
2. Реализуйте поведение `db_migration` (функции `up/0` и `down/0`).
|
||||
3. При очередном запуске приложения миграция будет применена.
|
||||
|
||||
## Откат миграций
|
||||
migration_engine:rollback("20260501120000_base_schema").
|
||||
|
||||
## Плавающее обновление (rolling update)
|
||||
1. Переведите узел в режим обслуживания.
|
||||
2. Выполните бэкап: `mnesia:backup("backup_node.bak")`.
|
||||
3. Обновите код приложения (git pull / rsync).
|
||||
4. Перезапустите узел – миграции применятся автоматически.
|
||||
5. Убедитесь в согласованности данных.
|
||||
6. Верните узел в работу.
|
||||
7. Повторите для остальных узлов.
|
||||
# Миграции схемы данных EventHub
|
||||
|
||||
## Когда применяются
|
||||
|
||||
После `infra_mnesia:init_tables()` и `wait_for_tables()` приложение вызывает
|
||||
`migration_engine:ensure_applied/0`:
|
||||
|
||||
1. Узел, захвативший **глобальную блокировку** в Mnesia (`schema_migration`, ключ `__migration_lock__`), применяет все pending-миграции.
|
||||
2. Остальные узлы (join кластера) **ждут**, пока pending-список станет пустым, и не стартуют HTTP до синхронизации.
|
||||
|
||||
Базовые таблицы создаёт `infra_mnesia` при старте. Миграции — только для **инкрементальных** изменений (индексы, трансформация данных, новые поля).
|
||||
|
||||
## Создание новой миграции
|
||||
|
||||
1. Создайте файл в `src/migrations/` с именем `YYYYMMDDHHMMSS_описание.erl`.
|
||||
2. Реализуйте `up/0` и `down/0`.
|
||||
3. Добавьте модуль в список `?ALL_MIGRATIONS` в `src/infra/migration_engine.erl` (в конец, по возрастанию версии).
|
||||
4. При следующем старте миграция применится автоматически (на узле с lock).
|
||||
|
||||
## Ручной запуск
|
||||
|
||||
```erlang
|
||||
migration_engine:apply_pending().
|
||||
migration_engine:status().
|
||||
migration_engine:rollback("20260501120000_base_schema").
|
||||
```
|
||||
|
||||
## Плавающее обновление (rolling update)
|
||||
|
||||
1. Переведите узел в режим обслуживания.
|
||||
2. Выполните бэкап: `mnesia:backup("backup_node.bak")`.
|
||||
3. Обновите код приложения (git pull / rsync).
|
||||
4. Перезапустите узел — `ensure_applied/0` применит только новые миграции (один узел с lock).
|
||||
5. Убедитесь: `migration_engine:status()` — `pending => []` на всех узлах.
|
||||
6. Верните узел в работу.
|
||||
7. Повторите для остальных узлов.
|
||||
|
||||
## Восстановление после сбоя
|
||||
|
||||
Если узел упал во время миграции, lock в `schema_migration` может остаться.
|
||||
Он считается устаревшим через **5 минут** (`?LOCK_STALE_SECONDS`) — следующий стартующий узел перехватит lock и продолжит.
|
||||
|
||||
При ошибке в `up/0` приложение не стартует (`{error, {migration_failed, ...}}`). Откатите код или исправьте миграцию, при необходимости восстановите из `mnesia:backup/1`.
|
||||
|
||||
Reference in New Issue
Block a user