MySQL-Backup auf neuerem Server — Kompatibilitätsprobleme lösen
Du hast einen sauberen mysqldump gemacht, spielst ihn auf dem neuen Server ein — und der Import bricht mit kryptischen Fehlermeldungen ab. Willkommen im Minenfeld der MySQL-Versionskompatibilität. Über die Jahre hat sich an der MySQL-Syntax einiges geändert, und ein Dump, der auf MySQL 4.x oder 5.0 erstellt wurde, läuft auf MySQL 8.0 nicht ohne Anpassungen durch.
Hier sind die häufigsten Kompatibilitätsprobleme und ihre Lösungen — sortiert nach Häufigkeit.
1. TYPE=MyISAM vs. ENGINE=MyISAM
Das ist der absolute Klassiker, wenn du Dumps aus der MySQL-4.x-Ära importierst.
Fehlermeldung
ERROR 1064 (42000): You have an error in your SQL syntax; check the manual
near 'TYPE=MyISAM' at line 25
Ursache
In MySQL 4.x und frühen 5.0-Versionen wurde die Storage Engine mit TYPE= angegeben. Ab MySQL 5.0 wurde ENGINE= eingeführt, TYPE= funktionierte aber noch als Alias. Ab MySQL 5.5 ist TYPE= komplett entfernt.
Lösung
Einfaches Suchen-und-Ersetzen in der Dump-Datei:
# Mit sed ersetzen
sed -i 's/TYPE=MyISAM/ENGINE=MyISAM/g' dump.sql
sed -i 's/TYPE=InnoDB/ENGINE=InnoDB/g' dump.sql
# Oder gleich alle TYPE=-Vorkommen
sed -i 's/TYPE=/ENGINE=/g' dump.sql
Falls du die Gelegenheit nutzen willst, um gleich auf InnoDB zu wechseln (empfohlen für die meisten Anwendungsfälle):
sed -i 's/ENGINE=MyISAM/ENGINE=InnoDB/g' dump.sql
2. Zeichensatz-Änderungen (CHARSET)
Fehlermeldung
ERROR 1115 (42000): Unknown character set: 'utf8mb3'
-- oder --
ERROR 1273 (HY000): Unknown collation: 'utf8mb4_0900_ai_ci'
Ursache
MySQL 8.0 hat den Standard-Zeichensatz von latin1 auf utf8mb4 geändert und eine neue Standard-Collation utf8mb4_0900_ai_ci eingeführt. Ältere MySQL-Versionen kennen diese Collation nicht. Umgekehrt verwenden manche MySQL-8.0-Dumps utf8mb3 als expliziten Alias für das alte utf8, was ältere Versionen nicht verstehen.
Lösung
# Unbekannte Collation in älteren MySQL-Versionen ersetzen
sed -i 's/utf8mb4_0900_ai_ci/utf8mb4_unicode_ci/g' dump.sql
# utf8mb3 durch utf8 ersetzen (für Import in ältere Versionen)
sed -i 's/utf8mb3/utf8/g' dump.sql
# Zeichensatz beim Import explizit setzen
mysql -u user -p --default-character-set=utf8mb4 datenbank < dump.sql
Mehr zu Zeichensatz-Problemen findest du im Artikel MySQL-Zeichensatz und Umlaute.
3. sql_mode STRICT (MySQL 5.7+)
Fehlermeldung
ERROR 1364 (HY000): Field 'email' doesn't have a default value
ERROR 1292 (22007): Incorrect date value: '0000-00-00' for column 'created_at'
Ursache
Ab MySQL 5.7 ist STRICT_TRANS_TABLES standardmäßig aktiviert. Das bedeutet:
- Fehlende Pflichtfelder ohne Default-Wert erzeugen einen Fehler statt einer Warnung
- Das Datum
0000-00-00wird nicht mehr akzeptiert - Leere Strings in numerische Spalten einzufügen schlägt fehl
Alte Dumps enthalten oft genau solche Daten, weil MySQL 5.5 und früher das alles stillschweigend akzeptiert hat.
Lösung
Am Anfang der Dump-Datei den sql_mode temporär lockern:
SET sql_mode = '';
SET GLOBAL sql_mode = '';
Oder beim Import direkt angeben:
mysql -u user -p --init-command="SET sql_mode=''" datenbank < dump.sql
Die nachhaltigere Lösung ist, die problematischen Daten im Dump zu korrigieren:
# 0000-00-00 Datumswerte durch NULL ersetzen
sed -i "s/'0000-00-00'/NULL/g" dump.sql
sed -i "s/'0000-00-00 00:00:00'/NULL/g" dump.sql
4. ROW_FORMAT-Probleme
Fehlermeldung
ERROR 1031 (HY000): Table storage engine for 'tabelle' doesn't have this option
ERROR 1005 (HY000): Can't create table (errno: 140 "Wrong create options")
Ursache
Dumps können explizite ROW_FORMAT-Angaben enthalten (z.B. ROW_FORMAT=FIXED, ROW_FORMAT=COMPRESSED), die auf dem Zielsystem nicht unterstützt werden. Besonders ROW_FORMAT=COMPRESSED erfordert das Barracuda-Dateiformat bei InnoDB.
Lösung
# ROW_FORMAT-Angaben entfernen
sed -i 's/ROW_FORMAT=[A-Z]*//g' dump.sql
Falls du ROW_FORMAT=COMPRESSED brauchst, muss auf dem Zielsystem Folgendes gesetzt sein:
[mysqld]
innodb_file_format = Barracuda
innodb_file_per_table = 1
5. Reservierte Wörter als Spalten- oder Tabellennamen
Fehlermeldung
ERROR 1064 (42000): You have an error in your SQL syntax; check the manual
near 'rank int(11)' at line 3
Ursache
MySQL erweitert mit jeder Version die Liste der reservierten Wörter. Was in MySQL 5.5 noch als Spaltenname erlaubt war, kann in MySQL 8.0 ein reserviertes Schlüsselwort sein. Bekannte Beispiele:
| Wort | Reserviert seit |
|---|---|
RANK |
MySQL 8.0 |
GROUPS |
MySQL 8.0 |
FUNCTION |
MySQL 8.0 |
SYSTEM |
MySQL 8.0 |
ROW |
MySQL 8.0 |
WINDOW |
MySQL 8.0 |
LATERAL |
MySQL 8.0.14 |
Lösung
Die betroffenen Bezeichner müssen mit Backticks escaped werden:
-- Vorher (funktioniert nicht in MySQL 8.0):
CREATE TABLE rankings (rank int(11), name varchar(255));
-- Nachher:
CREATE TABLE rankings (`rank` int(11), `name` varchar(255));
Ein guter mysqldump setzt standardmäßig Backticks um alle Bezeichner. Probleme entstehen meist bei manuell erstellten SQL-Dateien oder Dumps von sehr alten Tools.
# Prüfen, ob der Dump Backticks verwendet
head -50 dump.sql | grep "CREATE TABLE"
6. Integer Display Width deprecated (MySQL 8.0)
Warnmeldung
Warning 1681: Integer display width is deprecated and will be removed in a future release.
Ursache
In MySQL 8.0.17 wurde die Angabe der Display-Breite bei Integer-Typen als deprecated markiert. Das betrifft Definitionen wie int(11), tinyint(1), bigint(20). Die Zahl in Klammern hat nie die Speichergröße beeinflusst — sie bestimmte nur die Anzeigebreite bei ZEROFILL.
Lösung
Aktuell ist das nur eine Warnung, kein Fehler. Der Import funktioniert trotzdem. Wenn du die Warnungen loswerden willst:
# Display Width aus dem Dump entfernen
sed -i 's/int([0-9]*)/int/g' dump.sql
sed -i 's/bigint([0-9]*)/bigint/g' dump.sql
sed -i 's/tinyint([0-9]*)/tinyint/g' dump.sql
sed -i 's/smallint([0-9]*)/smallint/g' dump.sql
sed -i 's/mediumint([0-9]*)/mediumint/g' dump.sql
Achtung: tinyint(1) wird von vielen ORMs (z.B. in PHP/Laravel) als Boolean interpretiert. Wenn du das entfernst, kann es zu Problemen in der Anwendung kommen. Prüfe das vorher.
7. Authentication Plugin (MySQL 8.0)
Fehlermeldung
ERROR 2059 (HY000): Authentication plugin 'caching_sha2_password' cannot be loaded
Ursache
MySQL 8.0 verwendet standardmäßig caching_sha2_password statt mysql_native_password. Ältere Clients und PHP-Versionen unterstützen das nicht.
Lösung
Den Benutzer auf das alte Plugin umstellen:
ALTER USER 'dbuser'@'localhost' IDENTIFIED WITH mysql_native_password BY 'passwort';
Oder in der my.cnf global setzen:
[mysqld]
default_authentication_plugin = mysql_native_password
Strategie: Migration sicher testen
Bevor du einen Dump auf dem Produktivsystem einspielst, teste die Migration immer in einer sicheren Umgebung:
1. Lokale Testumgebung aufsetzen
# Docker-Container mit der Ziel-MySQL-Version starten
docker run -d --name mysql-test \
-e MYSQL_ROOT_PASSWORD=test \
-e MYSQL_DATABASE=testdb \
-p 3307:3306 \
mysql:8.0
# Dump importieren
mysql -h 127.0.0.1 -P 3307 -u root -ptest testdb < dump.sql
2. Fehler protokollieren
# Import mit Fehlerprotokoll
mysql -u root -p testdb < dump.sql 2> import_errors.log
# Fehler auswerten
cat import_errors.log | sort | uniq -c | sort -rn
3. Schrittweise korrigieren
Arbeite die Fehler systematisch ab. Erstelle ein Korrektur-Skript, das du auf den Dump anwendest:
#!/bin/bash
# fix_dump.sh — Kompatibilitäts-Fixes für MySQL 8.0
DUMP=$1
# TYPE= durch ENGINE= ersetzen
sed -i 's/TYPE=MyISAM/ENGINE=MyISAM/g' "$DUMP"
sed -i 's/TYPE=InnoDB/ENGINE=InnoDB/g' "$DUMP"
# Unbekannte Collation ersetzen
sed -i 's/utf8mb4_0900_ai_ci/utf8mb4_unicode_ci/g' "$DUMP"
# Ungültige Datumswerte korrigieren
sed -i "s/'0000-00-00'/NULL/g" "$DUMP"
sed -i "s/'0000-00-00 00:00:00'/NULL/g" "$DUMP"
# ROW_FORMAT entfernen
sed -i 's/ROW_FORMAT=[A-Z]*//g' "$DUMP"
echo "Fixes angewendet auf $DUMP"
4. Daten nach Import prüfen
# Tabellen zählen
SELECT COUNT(*) FROM information_schema.tables WHERE table_schema = 'testdb';
# Zeilenanzahl pro Tabelle
SELECT table_name, table_rows
FROM information_schema.tables
WHERE table_schema = 'testdb'
ORDER BY table_rows DESC;
Kompatibilitätsmatrix
| Dump-Quelle | Ziel-Version | Typische Probleme |
|---|---|---|
| MySQL 4.x | MySQL 5.7/8.0 | TYPE=, CHARSET, sql_mode strict |
| MySQL 5.0-5.5 | MySQL 5.7 | sql_mode strict, 0000-00-00 Daten |
| MySQL 5.5-5.6 | MySQL 8.0 | Reservierte Wörter, Display Width, Auth Plugin |
| MySQL 5.7 | MySQL 8.0 | Reservierte Wörter, Auth Plugin, Collation |
| MySQL 8.0 | MySQL 5.7 | utf8mb3-Alias, Window Functions, CTEs in Views |
| MySQL 8.0 | MariaDB 10.x | Collation, Auth Plugin, JSON-Syntax-Unterschiede |
Fazit
MySQL-Versionsinkompatibilitäten sind lästig, aber beherrschbar. Die meisten Probleme lassen sich mit ein paar gezielten sed-Befehlen vor dem Import lösen. Mein Rat: Teste den Import immer zuerst in einer Wegwerf-Umgebung (Docker ist dafür ideal), protokolliere die Fehler, und arbeite sie systematisch ab. So vermeidest du böse Überraschungen auf dem Produktivsystem.
Weiterführende Anleitungen findest du im mysqldump-Tutorial und im Artikel MySQL-Zeichensatz und Umlaute richtig konfigurieren.