Database Migrations Guide¶
Краткое руководство по работе с миграциями PostgreSQL в Saga.
Основные принципы¶
- НИКОГДА не изменяй схему БД вручную
- ВСЕГДА создавай миграции для изменений
- ОБРАТИМЫЕ миграции (up/down файлы)
- ТЕСТИРУЙ на копии production данных
Quick Commands¶
# Применить все миграции
make migration-up
# Откатить последнюю миграцию
make migration-down
# Проверить статус миграций
PGPASSWORD=aisee psql -U aisee -h 127.0.0.1 -d saga -c "SELECT version, dirty FROM schema_migrations"
Текущая схема¶
Консолидированная миграция¶
- 000001_consolidated_schema.up.sql - единая схема (429 строк)
- Все предыдущие миграции архивированы в
archive_20250716_153531/
Основные таблицы¶
users # Пользователи (БЕЗ wallet_address)
wallets # Кошельки с network_id INTEGER
transactions # Все финансовые операции (единый источник истины для балансов)
investments # Инвестиционные позиции
Создание новой миграции¶
1. Планирование¶
- Определи изменения: новые таблицы, колонки, индексы
- Проверь совместимость с существующими данными
- Спланируй rollback стратегию
2. Создание файлов¶
# Создать новую миграцию
make migration-create name=add_user_preferences
# Это создаст:
# 000004_add_user_preferences.up.sql
# 000004_add_user_preferences.down.sql
3. Написание миграций¶
UP миграция (000004_add_user_preferences.up.sql):
-- Добавление новой таблицы
CREATE TABLE user_preferences (
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
user_id UUID NOT NULL REFERENCES users(id) ON DELETE CASCADE,
preferences JSONB NOT NULL DEFAULT '{}',
created_at TIMESTAMP WITH TIME ZONE NOT NULL DEFAULT NOW(),
updated_at TIMESTAMP WITH TIME ZONE NOT NULL DEFAULT NOW()
);
-- Индекс для быстрого поиска
CREATE INDEX idx_user_preferences_user_id ON user_preferences(user_id);
-- Комментарии
COMMENT ON TABLE user_preferences IS 'Пользовательские настройки и предпочтения';
DOWN миграция (000004_add_user_preferences.down.sql):
-- Откат в обратном порядке
DROP INDEX IF EXISTS idx_user_preferences_user_id;
DROP TABLE IF EXISTS user_preferences;
Best Practices¶
Безопасные операции¶
- ADD COLUMN с DEFAULT значениями
- CREATE INDEX CONCURRENTLY для больших таблиц
- ADD CONSTRAINT для новых данных
Опасные операции¶
- DROP COLUMN - потеря данных
- ALTER COLUMN TYPE - может блокировать таблицу
- DROP TABLE - необратимо
Шаблон безопасной миграции¶
-- Добавление колонки с DEFAULT
ALTER TABLE users ADD COLUMN phone VARCHAR(20) DEFAULT '';
-- Обновление существующих данных (если нужно)
UPDATE users SET phone = '' WHERE phone IS NULL;
-- Добавление NOT NULL constraint (после заполнения данных)
ALTER TABLE users ALTER COLUMN phone SET NOT NULL;
Тестирование миграций¶
Локальное тестирование¶
# 1. Создать backup тестовой БД
pg_dump -U aisee -h 127.0.0.1 saga > backup_before_migration.sql
# 2. Применить миграцию
make migration-up
# 3. Проверить что всё работает
make test-smoke
# 4. Откатить (если проблемы)
make migration-down
# 5. Восстановить из backup (если критично)
dropdb -U aisee -h 127.0.0.1 saga
createdb -U aisee -h 127.0.0.1 saga
psql -U aisee -h 127.0.0.1 saga < backup_before_migration.sql
Production чек-лист¶
- Миграция протестирована на копии production данных
- Rollback процедура проверена
- Backup создан перед миграцией
- Downtime запланирован (если нужен)
- Мониторинг настроен
Troubleshooting¶
"Migration failed: table already exists"¶
# Проверить текущее состояние
PGPASSWORD=aisee psql -U aisee -h 127.0.0.1 -d saga -c "\dt"
# Пометить миграцию как примененную (осторожно!)
PGPASSWORD=aisee psql -U aisee -h 127.0.0.1 -d saga -c "INSERT INTO schema_migrations (version, dirty) VALUES (4, false)"
"Migration stuck in dirty state"¶
# Очистить dirty состояние (ОСТОРОЖНО!)
PGPASSWORD=aisee psql -U aisee -h 127.0.0.1 -d saga -c "UPDATE schema_migrations SET dirty = false WHERE version = 4"
# Затем попробовать снова
make migration-down
Production миграция не применяется¶
- Проверь схему production БД
- Создай промежуточные миграции для приведения к консистентному состоянию
- НЕ форсируй миграцию - это может сломать production
Схема миграций¶
storage/migrations/
├── 000001_consolidated_schema.up.sql # Основная схема
├── 000001_consolidated_schema.down.sql # Откат основной схемы
├── 000002_add_deleted_at.up.sql # Soft delete
├── 000003_drop_withdrawals.up.sql # Удаление таблицы withdrawals
└── archive_20250716_153531/ # Архив старых миграций
Золотое правило: Лучше создать лишнюю миграцию, чем сломать production БД ручными изменениями.
Связанные документы¶
Исправления и примеры: - Template Database Schema Fix (2025-10-02) - Исправление template базы данных для изолированного тестирования (gen_random_uuid DEFAULT)