#!/bin/bash # Migriert die Datenbank von latin1 auf utf8mb4. # Läuft auf dem Server im Verzeichnis der compose.yml. # Voraussetzung: iconv installiert (apt install libc-bin) set -e CONTAINER="logbuch_mysql" DB="sternwarte" DUMP_LATIN1="/tmp/sternwarte_latin1.sql" DUMP_UTF8="/tmp/sternwarte_utf8mb4.sql" # Root-Passwort aus .env lesen ROOT_PASS=$(grep DB_ROOT_PASS .env | cut -d= -f2) if [ -z "$ROOT_PASS" ]; then echo "FEHLER: DB_ROOT_PASS nicht in .env gefunden." >&2 exit 1 fi echo "══════════════════════════════════════════════════════" echo " latin1 → utf8mb4 Migration: $DB" echo "══════════════════════════════════════════════════════" echo "" # ── Sicherheits-Backup ─────────────────────────────────────────────────────── BACKUP="/tmp/sternwarte_backup_$(date +%Y%m%d_%H%M%S).sql" echo ">>> Erstelle Backup: $BACKUP" docker exec "$CONTAINER" mysqldump \ -u root -p"$ROOT_PASS" \ --default-character-set=latin1 \ --single-transaction \ --no-tablespaces \ --set-gtid-purged=OFF \ "$DB" > "$BACKUP" echo " Backup gespeichert: $BACKUP" echo "" # ── Dump als latin1 exportieren ────────────────────────────────────────────── echo ">>> Exportiere Daten mit latin1-Zeichensatz..." docker exec "$CONTAINER" mysqldump \ -u root -p"$ROOT_PASS" \ --default-character-set=latin1 \ --single-transaction \ --no-tablespaces \ --skip-set-charset \ --set-gtid-purged=OFF \ "$DB" > "$DUMP_LATIN1" echo " Dump: $DUMP_LATIN1" echo "" # ── Bytes latin1 → utf8 konvertieren ──────────────────────────────────────── echo ">>> Konvertiere Bytes: latin1 → utf8..." iconv -f latin1 -t utf8 "$DUMP_LATIN1" > "$DUMP_UTF8" # Charset-Deklarationen im SQL ersetzen sed -i \ -e 's/DEFAULT CHARSET=latin1/DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci/g' \ -e 's/COLLATE=latin1_swedish_ci//g' \ -e 's/CHARACTER SET latin1/CHARACTER SET utf8mb4/g' \ -e 's/COLLATE latin1_swedish_ci/COLLATE utf8mb4_unicode_ci/g' \ "$DUMP_UTF8" echo " Konvertiert: $DUMP_UTF8" echo "" # ── Zeilenzähler vor Migration ─────────────────────────────────────────────── echo ">>> Zeilenzähler vor Migration:" for TABLE in beos objekte logbuch logbuch_beos logbuch_objekte; do COUNT=$(docker exec "$CONTAINER" mysql -u root -p"$ROOT_PASS" -sN \ -e "SELECT COUNT(*) FROM $TABLE;" "$DB" 2>/dev/null || echo "n/a") printf " %-25s %5s Zeilen\n" "$TABLE" "$COUNT" done echo "" # ── Zieldatenbank anlegen ──────────────────────────────────────────────────── echo ">>> Lege Zieldatenbank an (utf8mb4)..." docker exec -i "$CONTAINER" mysql -u root -p"$ROOT_PASS" <>> Importiere utf8mb4-Daten..." docker exec -i "$CONTAINER" mysql \ -u root -p"$ROOT_PASS" \ --default-character-set=utf8mb4 \ "${DB}_new" < "$DUMP_UTF8" # ── Zeilenzähler nach Migration ────────────────────────────────────────────── echo "" echo ">>> Zeilenzähler nach Migration:" ALL_OK=true for TABLE in beos objekte logbuch logbuch_beos logbuch_objekte; do BEFORE=$(docker exec "$CONTAINER" mysql -u root -p"$ROOT_PASS" -sN \ -e "SELECT COUNT(*) FROM $TABLE;" "${DB}" 2>/dev/null || echo "?") AFTER=$(docker exec "$CONTAINER" mysql -u root -p"$ROOT_PASS" -sN \ -e "SELECT COUNT(*) FROM $TABLE;" "${DB}_new" 2>/dev/null || echo "?") STATUS="✓" [ "$BEFORE" != "$AFTER" ] && STATUS="✗ ABWEICHUNG" && ALL_OK=false printf " %-25s %5s → %5s %s\n" "$TABLE" "$BEFORE" "$AFTER" "$STATUS" done echo "" if [ "$ALL_OK" = false ]; then echo "FEHLER: Zeilenzähler stimmen nicht überein!" >&2 echo "Datenbank '${DB}_new' bleibt zur manuellen Prüfung erhalten." >&2 exit 1 fi # ── Swap: sternwarte → sternwarte_old, sternwarte_new → sternwarte ─────────── echo ">>> Alle Zeilenzähler stimmen — tausche Datenbanken..." TABLES=$(docker exec "$CONTAINER" mysql -u root -p"$ROOT_PASS" -sN \ -e "SHOW TABLES;" "${DB}_new") # Alte DB umbenennen (Tabellen nach sternwarte_old verschieben) docker exec "$CONTAINER" mysql -u root -p"$ROOT_PASS" -e \ "CREATE DATABASE IF NOT EXISTS ${DB}_old CHARACTER SET latin1;" for TABLE in $TABLES; do docker exec "$CONTAINER" mysql -u root -p"$ROOT_PASS" -e \ "RENAME TABLE \`${DB}\`.\`$TABLE\` TO \`${DB}_old\`.\`$TABLE\`;" done # Neue DB nach sternwarte verschieben docker exec "$CONTAINER" mysql -u root -p"$ROOT_PASS" -e \ "ALTER DATABASE ${DB} CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;" for TABLE in $TABLES; do docker exec "$CONTAINER" mysql -u root -p"$ROOT_PASS" -e \ "RENAME TABLE \`${DB}_new\`.\`$TABLE\` TO \`${DB}\`.\`$TABLE\`;" done docker exec "$CONTAINER" mysql -u root -p"$ROOT_PASS" -e \ "DROP DATABASE ${DB}_new; DROP DATABASE ${DB}_old;" # ── Kollation bestätigen ───────────────────────────────────────────────────── echo "" echo ">>> Kollation der Tabellen:" docker exec "$CONTAINER" mysql -u root -p"$ROOT_PASS" -e \ "SELECT TABLE_NAME, TABLE_COLLATION FROM information_schema.TABLES WHERE TABLE_SCHEMA = '$DB' ORDER BY TABLE_NAME;" 2>/dev/null echo "" echo "══════════════════════════════════════════════════════" echo " Migration erfolgreich abgeschlossen!" echo " Backup: $BACKUP" echo " App neu starten: docker compose up -d logbuch_app" echo "══════════════════════════════════════════════════════"