- .gitignore: .claude/docs, rules, commands tracken; settings.local weiter ignorieren - DOCUMENTATION.md: verbindliche Ablage functional/technical/working/issues - .claude/README.md: Agent-Einstieg; GITEA_ISSUES_INDEX aus MCP (Stand 2026-04-08) - Arbeitspapiere von docs/ nach .claude/docs/working/ verschoben - docs/MEMBERSHIP_SYSTEM.md als Stub; kanonisch technical/MEMBERSHIP_SYSTEM.md - CLAUDE.md Pflichtlektüre und Links angepasst; docs/README.md vereinfacht Made-with: Cursor
11 KiB
Database Migrations System
Version: v9c Implementiert: 2026-03-21 Dokumentiert: 2026-03-21
Übersicht
Mitai Jinkendo verwendet ein automatisches Migrations-System für strukturierte Schema-Änderungen. Alle Migrationen werden beim Container-Start automatisch ausgeführt.
Architektur
Migration-Tracking
Tabelle: schema_migrations
CREATE TABLE schema_migrations (
id SERIAL PRIMARY KEY,
filename VARCHAR(255) UNIQUE NOT NULL,
applied_at TIMESTAMP WITH TIME ZONE DEFAULT CURRENT_TIMESTAMP
)
Diese Tabelle trackt, welche Migrationen bereits angewendet wurden.
Ablauf beim Container-Start
- PostgreSQL Connection Check (
db_init.py) - Schema-Initialisierung (falls
profilesTabelle nicht existiert)- Lädt
backend/schema.sql(Basis-Schema)
- Lädt
- Migrations-System (
run_migrations())- Erstellt
schema_migrationsTabelle (falls nicht vorhanden) - Scannt
backend/migrations/nach.sqlDateien - Filtert nur nummerierte Dateien:
\d{3}_*.sql(z.B.001_feature.sql) - Sortiert alphabetisch (aufsteigende Reihenfolge)
- Wendet nur noch nicht angewendete Migrationen an
- Trackt jede erfolgreich angewendete Migration
- Erstellt
- SQLite-zu-PostgreSQL Migration (falls vorhanden)
Datei-Konventionen
Naming-Pattern
Format: XXX_descriptive_name.sql
XXX= Dreistellige Nummer (001, 002, 003, ...)- Unterstrich
_als Trennzeichen - Kleinbuchstaben, keine Leerzeichen
.sqlExtension
Beispiele:
✅ 001_subscription_system.sql
✅ 002_fix_features.sql
✅ 003_add_email_verification.sql
❌ v9c_subscription_system.sql # Keine Nummer
❌ check_features.sql # Keine Nummer
❌ 1_feature.sql # Nur eine Ziffer
❌ 001-feature.sql # Bindestrich statt Unterstrich
Datei-Struktur
Jede Migration sollte folgende Struktur haben:
-- ================================================================
-- Migration XXX: Beschreibung
-- Version: vX.X
-- Date: YYYY-MM-DD
-- ================================================================
-- Beschreibung der Änderung
ALTER TABLE table_name ...
-- Weitere SQL-Statements
-- Kommentare für Dokumentation
COMMENT ON COLUMN table.column IS 'Beschreibung';
SQL-Einschränkungen
Erlaubt:
- Standard SQL DDL (CREATE, ALTER, DROP)
- Standard SQL DML (INSERT, UPDATE, DELETE)
- CREATE INDEX, CREATE FUNCTION, etc.
- Multi-Statement-Scripts (durch
;getrennt)
Nicht erlaubt:
- psql Meta-Kommandos (
\echo,\set,\connect, etc.) - Interactive Commands (
\i,\include) - Transaktions-Kontrolle (automatisch gehandhabt)
Anwendung
Automatisch (Production/Dev)
Migrationen werden automatisch beim Container-Start angewendet:
# Container startet
docker compose up -d
# db_init.py wird ausgeführt:
# 1. PostgreSQL ready check
# 2. Schema initialisiert (falls nötig)
# 3. Migrationen ausgeführt
# 4. SQLite-Migration (falls nötig)
Log-Output:
═══════════════════════════════════════════════════════════
MITAI JINKENDO - Database Initialization (v9c)
═══════════════════════════════════════════════════════════
Checking PostgreSQL connection...
✓ PostgreSQL ready
Checking database schema...
✓ Schema already exists
Running database migrations...
Found 2 pending migration(s)...
✓ Applied: 001_subscription_system.sql
✓ Applied: 003_add_email_verification.sql
✓ Database initialization complete
Manuell (Entwicklung)
Für Testing während der Entwicklung:
# Im laufenden Container
docker exec -it dev-mitai-api python3 /app/db_init.py
# Oder direkt mit psql (für einzelne Migrationen)
docker exec -it dev-mitai-db psql -U mitai_dev -d mitai_dev \
-f /path/to/migration.sql
Migration erstellen
Schritt 1: Datei erstellen
# Nächste freie Nummer ermitteln
ls backend/migrations/ | grep -E '^\d{3}_' | sort | tail -1
# → 003_add_email_verification.sql
# Neue Migration mit Nummer 004
touch backend/migrations/004_add_new_feature.sql
Schritt 2: SQL schreiben
-- ================================================================
-- Migration 004: Add New Feature
-- Version: v9d
-- Date: 2026-03-22
-- ================================================================
-- Add new column
ALTER TABLE profiles
ADD COLUMN IF NOT EXISTS new_feature_enabled BOOLEAN DEFAULT TRUE;
-- Create index if needed
CREATE INDEX IF NOT EXISTS idx_profiles_new_feature
ON profiles(new_feature_enabled)
WHERE new_feature_enabled = TRUE;
-- Update existing data if needed
UPDATE profiles
SET new_feature_enabled = TRUE
WHERE tier = 'premium';
COMMENT ON COLUMN profiles.new_feature_enabled IS 'Feature flag for new feature';
Schritt 3: Testen
# Lokal testen (Dev-Container)
git add backend/migrations/004_add_new_feature.sql
git commit -m "feat: add migration for new feature"
git push origin develop
# Container wird neu gebaut und Migration automatisch angewendet
Schritt 4: Verifizieren
# Prüfen ob Migration angewendet wurde
docker exec -it dev-mitai-db psql -U mitai_dev -d mitai_dev \
-c "SELECT * FROM schema_migrations ORDER BY applied_at DESC LIMIT 5;"
# Output:
# id | filename | applied_at
# ---+------------------------------+------------------------
# 4 | 004_add_new_feature.sql | 2026-03-22 10:30:15+00
# 3 | 003_add_email_verification.sql| 2026-03-21 15:20:10+00
# 2 | 002_fix_features.sql | 2026-03-20 12:10:05+00
# 1 | 001_subscription_system.sql | 2026-03-20 12:10:00+00
Rollback-Strategie
Automatischer Rollback: Nicht implementiert
Manueller Rollback:
-
Identifizieren der problematischen Migration:
docker logs dev-mitai-api | grep "Failed to apply" -
Migration aus Tracking entfernen:
DELETE FROM schema_migrations WHERE filename = '004_broken_migration.sql'; -
Änderungen manuell rückgängig machen:
-- Beispiel: Spalte entfernen ALTER TABLE profiles DROP COLUMN new_feature_enabled; -
Migration-Datei korrigieren
vim backend/migrations/004_broken_migration.sql -
Container neu starten (Migration wird erneut ausgeführt)
docker compose restart api
Best Practices
✅ DO
-
Immer
IF NOT EXISTS/IF EXISTSverwenden:ALTER TABLE profiles ADD COLUMN IF NOT EXISTS email_verified BOOLEAN; CREATE INDEX IF NOT EXISTS idx_profiles_email ON profiles(email); -
Idempotente Migrationen schreiben: Migration kann mehrfach ausgeführt werden ohne Fehler
-
Daten-Migrationen mit Bedacht:
UPDATE profiles SET email_verified = TRUE WHERE email IS NOT NULL AND email_verified IS NULL; -
Kommentare für Dokumentation:
COMMENT ON COLUMN profiles.email_verified IS 'Whether email has been verified'; -
Indices für Performance:
CREATE INDEX IF NOT EXISTS idx_profiles_verification_token ON profiles(verification_token) WHERE verification_token IS NOT NULL; -- Partial index
❌ DON'T
-
Keine psql Meta-Kommandos:
\echo "Starting migration" -- ❌ Funktioniert nicht SELECT 'Starting migration'; -- ✅ Funktioniert -
Keine Breaking Changes ohne Staging:
ALTER TABLE profiles DROP COLUMN tier; -- ❌ App wird brechen -
Keine Hardcoded Values für produktive Daten:
INSERT INTO profiles (id, email, ...) VALUES (1, 'admin@example.com', ...); -- ❌ -
Keine Foreign Keys ohne Fallback:
-- ❌ Ohne ON DELETE Behavior ALTER TABLE subscriptions ADD CONSTRAINT fk_profile FOREIGN KEY (profile_id) REFERENCES profiles(id); -- ✅ Mit Cascade ALTER TABLE subscriptions ADD CONSTRAINT fk_profile FOREIGN KEY (profile_id) REFERENCES profiles(id) ON DELETE CASCADE;
Troubleshooting
Migration schlägt fehl
Symptom: Container startet nicht, Logs zeigen ✗ Failed to apply XXX.sql
Lösung:
- Logs prüfen:
docker logs dev-mitai-api | tail -50 - Fehlerhafte Migration identifizieren
- Aus Tracking entfernen + Schema manuell korrigieren
- Migration-Datei fixen
- Container neu starten
Migration wurde nicht angewendet
Symptom: Neue Migration-Datei wird ignoriert
Ursachen:
- Datei entspricht nicht dem Pattern
\d{3}_*.sql - Datei wurde bereits in
schema_migrationsgetrackt - Datei ist nicht im Container (
backend/migrations/Volume gemountet?)
Lösung:
# Prüfen ob Datei gemountet ist
docker exec -it dev-mitai-api ls -la /app/migrations/
# Prüfen ob bereits getrackt
docker exec -it dev-mitai-db psql -U mitai_dev -d mitai_dev \
-c "SELECT * FROM schema_migrations WHERE filename = '004_feature.sql';"
# Falls fälschlich getrackt, entfernen
docker exec -it dev-mitai-db psql -U mitai_dev -d mitai_dev \
-c "DELETE FROM schema_migrations WHERE filename = '004_feature.sql';"
# Container neu starten
docker compose restart api
Datenbank-Schema inkonsistent
Symptom: schema_migrations zeigt Migration als angewendet, aber Änderungen fehlen
Ursachen:
- Migration wurde manuell ausgeführt, aber Tracking war kaputt
- Datenbank wurde zurückgesetzt, aber Tracking-Tabelle nicht
Lösung:
# Schema neu aufbauen (ACHTUNG: Datenverlust!)
docker compose down -v # Löscht Volumes
docker compose up -d # Baut alles neu auf
# ODER: Tracking-Tabelle manuell korrigieren
docker exec -it dev-mitai-db psql -U mitai_dev -d mitai_dev \
-c "TRUNCATE schema_migrations; -- Alle Tracking-Einträge löschen"
# Container neu starten → Alle Migrationen werden erneut angewendet
docker compose restart api
Migrations-Historie
| Nr. | Datei | Version | Datum | Beschreibung |
|---|---|---|---|---|
| 003 | 003_add_email_verification.sql |
v9c | 2026-03-21 | Email-Verifizierung (verification_token, email_verified, verification_expires) |
| 002 | 002_fix_features.sql (manuell) |
v9c | 2026-03-20 | Feature-System Fixes |
| 001 | 001_subscription_system.sql (manuell) |
v9c | 2026-03-20 | Membership-System (tiers, subscriptions, coupons, access_grants) |
Hinweis: Migrationen 001 und 002 wurden vor Einführung des automatischen Systems manuell angewendet und sind nicht nummeriert. Ab Migration 003 läuft alles automatisch.
Referenzen
- Code:
backend/db_init.py(Zeilen 94-200) - Migrations-Ordner:
backend/migrations/ - Tracking-Tabelle:
schema_migrations - Startup-Script:
backend/startup.sh(ruftdb_init.pyauf) - Dokumentation:
.claude/docs/technical/MIGRATIONS.md(diese Datei)
Dokumentiert: 2026-03-21 Letzte Änderung: 2026-03-21