Charset und Collation: utf8mb4 richtig einsetzen
AI generated
InnoDB
SQL
MySQL · Unicode · Zeichensatz · Internationalisierung
Charset und Collation: utf8mb4 richtig einsetzen
warum utf8 in MySQL kein echtes Unicode ist

Der Zeichensatz utf8 in MySQL ist eine historische Falle, die maximal drei Byte pro Zeichen erlaubt und damit Emoji sowie viele seltene Schriftzeichen stillschweigend verwirft oder Fehler wirft. utf8mb4 bildet echtes Unicode vollständig ab, verlangt aber die richtige Collation-Wahl und eine sauber geplante Migration, um Indexlängen und Sortierreihenfolgen nicht zu brechen.

17 Min. Lesezeit utf8mb4 · Collation · Unicode · Migration MySQL 8.0 · InnoDB

1. Die utf8-Legacy-Falle in MySQL

Der in MySQL als utf8 bezeichnete Charset ist entgegen seines Namens kein vollständiges Unicode. Er wurde vor der offiziellen Unicode-3-Byte-Grenze eingeführt und kodiert maximal drei Byte pro Zeichen, während der vollständige Unicode-Standard bis zu vier Byte pro Codepunkt benötigt. Zeichen außerhalb der Basic Multilingual Plane, darunter praktisch alle Emoji, viele seltene chinesische Schriftzeichen und historische Alphabete, lassen sich mit diesem Charset schlicht nicht abbilden.

Das führt in der Praxis zu zwei Symptomen: Entweder wirft MySQL beim Einfügen eines Emoji einen Fehler wie Incorrect string value, oder, bei laxeren SQL-Modi, das Zeichen wird stillschweigend durch ein Fragezeichen oder ein leeres Zeichen ersetzt. Letzteres ist besonders gefährlich, weil der Datenverlust unbemerkt bleibt, bis jemand die betroffenen Datensätze manuell prüft. Gerade bei nutzergenerierten Inhalten wie Kommentaren, Produktnamen oder Chat-Nachrichten trifft dieses Problem praktisch jede Anwendung früher oder später.

MySQL hat diese historische Altlast mit dem Charset utf8mb4 korrigiert, der als der eigentliche, vollständige Unicode-Charset zu verstehen ist. Seit MySQL 8.0 ist utf8mb4 sogar der Standard-Charset neuer Datenbanken, was zeigt, wie klar sich die Empfehlung inzwischen durchgesetzt hat. Wer heute noch utf8 verwendet, tut das entweder aus Unwissenheit oder wegen einer alten, nicht migrierten Installation.

2. utf8mb4: was sich technisch ändert

utf8mb4 nutzt bis zu vier Byte pro Zeichen und deckt damit den gesamten Unicode-Codepunkt-Bereich ab, inklusive aller Emoji, Supplementary-Plane-Zeichen und seltener Sprachsysteme. Der Umstieg betrifft nicht nur den Charset einer Tabelle, sondern auch die maximale Byteanzahl, die MySQL für VARCHAR- und CHAR-Spalten intern reserviert, was direkte Auswirkungen auf Indexlängen hat, dazu mehr im Abschnitt zur Indexlänge.

Der Wechsel von utf8 zu utf8mb4 ist rückwärtskompatibel in dem Sinn, dass alle mit utf8 gespeicherten Zeichen auch in utf8mb4 korrekt dargestellt werden. Die Migration verläuft daher stets in eine Richtung, ein Downgrade von utf8mb4 zurück zu utf8 würde Daten zerstören, sobald 4-Byte-Zeichen enthalten sind. Deshalb sollte jede neue Tabelle von Anfang an mit utf8mb4 angelegt werden, selbst wenn aktuell kein Bedarf für Emoji-Unterstützung besteht.


-- Wrong: legacy charset, cannot store most emoji
CREATE TABLE product_review_old (
  id INT UNSIGNED NOT NULL AUTO_INCREMENT,
  comment VARCHAR(500),
  PRIMARY KEY (id)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

-- Right: full Unicode support including emoji
CREATE TABLE product_review (
  id INT UNSIGNED NOT NULL AUTO_INCREMENT,
  comment VARCHAR(500),
  PRIMARY KEY (id)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci;

-- Verify actual byte width in use
SELECT CHAR_LENGTH('????'), LENGTH('????');
-- CHAR_LENGTH = 1 (one character), LENGTH = 4 (four bytes in utf8mb4)

3. Collation-Grundlagen: Vergleich und Sortierung

Eine Collation definiert, wie MySQL Zeichen vergleicht und sortiert, unabhängig vom Charset, in dem sie gespeichert sind. Jeder Charset hat mehrere mögliche Collations, die sich in Groß-Kleinschreibung-Sensitivität, Akzent-Sensitivität und der Sortierreihenfolge sprachspezifischer Zeichen unterscheiden. Das Suffix _ci steht für case-insensitive, _cs für case-sensitive und _bin für einen reinen Byte-für-Byte-Vergleich ohne linguistische Regeln.

Die falsche Collation-Wahl führt zu subtilen Bugs, die oft erst spät auffallen: Ein Login mit E-Mail-Adresse funktioniert bei einer case-insensitive Collation unabhängig von Groß- und Kleinschreibung, was für E-Mail-Vergleiche meist erwünscht ist, bei einer case-sensitive Collation dagegen nicht. Umgekehrt kann eine ungewollt case-insensitive Collation bei Produktcodes dazu führen, dass ABC-123 und abc-123 als identisch behandelt werden, obwohl das fachlich falsch ist.

4. unicode_ci vs. 0900_ai_ci: die richtige Wahl treffen

Für utf8mb4 stehen mehrere Standard-Collations zur Verfügung, wobei in der Praxis vor allem zwei relevant sind: utf8mb4_unicode_ci, die auf dem älteren Unicode Collation Algorithm UCA 4.0.0 basiert, und utf8mb4_0900_ai_ci, die seit MySQL 8.0 auf UCA 9.0.0 aufsetzt und deutlich genauer mit modernen Sprachregeln umgeht. Das Kürzel 0900 verweist auf die UCA-Version, ai steht für accent-insensitive, ci für case-insensitive.

Für neue MySQL-8-Installationen ist utf8mb4_0900_ai_ci in aller Regel die richtige Standardwahl, weil sie präzisere Sortierregeln für viele Sprachen mitbringt und zudem messbar performanter arbeitet als die ältere unicode_ci-Variante. Ein wichtiger Sonderfall betrifft binäre Vergleiche: Wer Sortierung und Vergleich exakt nach Unicode-Codepunkt ohne linguistische Regeln braucht, etwa für technische Identifikatoren oder Hashes, sollte utf8mb4_bin verwenden, weil dort keine Zeichen als äquivalent behandelt werden.


-- Check available utf8mb4 collations
SHOW COLLATION WHERE Charset = 'utf8mb4';

-- Case-insensitive, accent-insensitive: good default for user-facing text
ALTER TABLE customer
  MODIFY email VARCHAR(255)
  CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci;

-- Case-sensitive, exact match: good for technical identifiers
ALTER TABLE api_token
  MODIFY token_hash VARCHAR(64)
  CHARACTER SET utf8mb4 COLLATE utf8mb4_bin;

-- Comparison example: same word, different collation behavior
SELECT 'café' = 'cafe' COLLATE utf8mb4_0900_as_ci;   -- accent-sensitive: 0
SELECT 'café' = 'cafe' COLLATE utf8mb4_0900_ai_ci;   -- accent-insensitive: 1

5. Indexlänge und der klassische Schlüssel-zu-lang-Fehler

Der Wechsel von utf8 zu utf8mb4 erhöht die maximal benötigte Byteanzahl pro Zeichen von drei auf vier, was direkte Auswirkungen auf Indizes hat. InnoDB begrenzt Indexschlüssel in der Standardkonfiguration auf 767 Byte für das ältere Antelope-Dateiformat beziehungsweise 3072 Byte für Barracuda mit aktiviertem innodb_large_prefix, was seit MySQL 5.7 Standard ist. Bei einem VARCHAR(255)-Feld mit utf8 ergeben sich maximal 765 Byte, was gerade noch unter das alte Limit passt. Mit utf8mb4 wären es 1020 Byte, was den klassischen Fehler Specified key was too long auslöst, sofern das alte Limit noch aktiv ist.

In modernen MySQL-8-Installationen mit dem Standard-Dateiformat ist das 3072-Byte-Limit bereits aktiv, wodurch dieses Problem in der Regel nicht mehr auftritt. Bei der Migration älterer Installationen oder beim Import von Dumps aus älteren MySQL-Versionen lohnt sich dennoch ein gezielter Blick auf Indizes mit langen VARCHAR-Spalten, insbesondere zusammengesetzte Indizes, deren kumulierte Byteanzahl schnell das Limit überschreiten kann.


-- Find indexes at risk after switching to utf8mb4
-- (varchar length * 4 bytes must stay under the innodb key length limit)
SELECT table_name, column_name, character_maximum_length,
       character_maximum_length * 4 AS max_bytes_utf8mb4
FROM information_schema.columns
WHERE table_schema = 'shop'
  AND data_type IN ('varchar', 'char')
  AND character_maximum_length * 4 > 767
ORDER BY max_bytes_utf8mb4 DESC;

-- Confirm the active row format and large prefix support
SHOW VARIABLES LIKE 'innodb_file_format';
SHOW VARIABLES LIKE 'innodb_large_prefix';

6. Server-, Verbindungs- und Anwendungscharset synchron halten

Ein häufiger Fehler bei der Migration betrifft nicht die Tabellen selbst, sondern die Verbindungsebene. Selbst wenn alle Tabellen korrekt auf utf8mb4 stehen, sendet ein PHP- oder Node-Client, der die Verbindung noch mit utf8 initialisiert, Daten in einem inkonsistenten Charset, was zu Mojibake, also fehlerhaft dargestellten Zeichen, führt. Die Verbindung muss explizit mit utf8mb4 aufgebaut werden, entweder über den Connection-String, über SET NAMES utf8mb4 direkt nach dem Verbindungsaufbau, oder über die entsprechende Client-Bibliothekskonfiguration.

Auch die serverseitige my.cnf-Konfiguration sollte konsistent auf utf8mb4 stehen, damit neu erstellte Datenbanken und Tabellen ohne explizite Angabe automatisch den richtigen Charset erhalten. Fehlt diese Konfiguration, verlässt man sich bei jeder CREATE TABLE-Anweisung darauf, dass Entwickler den Charset nicht vergessen, was in der Praxis irgendwann garantiert passiert.


# my.cnf: consistent utf8mb4 across server, client and connection
[mysqld]
character-set-server = utf8mb4
collation-server = utf8mb4_0900_ai_ci
skip-character-set-client-handshake

[client]
default-character-set = utf8mb4

[mysql]
default-character-set = utf8mb4

7. Migration von utf8 zu utf8mb4 in der Praxis

Eine saubere Migration von utf8 zu utf8mb4 läuft in mehreren kontrollierten Schritten ab. Zuerst wird die Serverkonfiguration angepasst, damit neue Objekte korrekt angelegt werden. Anschließend werden bestehende Datenbanken, Tabellen und Spalten schrittweise per ALTER TABLE ... CONVERT TO CHARACTER SET utf8mb4 konvertiert. Wichtig: CONVERT TO CHARACTER SET ändert sowohl den Charset der Tabelle als auch aller ihrer Spalten in einem Schritt, was für die meisten Migrationen der richtige, effizienteste Weg ist.

Vor der Migration sollte immer ein vollständiges Backup existieren, weil die Konvertierung bei sehr großen Tabellen lange dauern und im Fehlerfall zu inkonsistenten Zwischenzuständen führen kann. Für Produktionsumgebungen mit hohem Traffic empfiehlt sich außerdem, die Konvertierung tabellenweise während eines Wartungsfensters durchzuführen, statt die gesamte Datenbank in einem einzigen, langen Sperr-verursachenden Vorgang umzustellen.


-- Step 1: convert the database default
ALTER DATABASE shop CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci;

-- Step 2: convert each table (data and columns in one operation)
ALTER TABLE shop.customer
  CONVERT TO CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci;

ALTER TABLE shop.product_review
  CONVERT TO CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci;

-- Step 3: verify no column is still on the legacy charset
SELECT table_name, column_name, character_set_name, collation_name
FROM information_schema.columns
WHERE table_schema = 'shop'
  AND character_set_name IS NOT NULL
  AND character_set_name != 'utf8mb4';

8. Typische Fallstricke nach der Migration

Nach einer scheinbar abgeschlossenen Migration tauchen häufig noch Zwischenspeicher-Objekte mit dem alten Charset auf: Views, gespeicherte Prozeduren und Trigger übernehmen den Charset zum Zeitpunkt ihrer Erstellung und werden von ALTER TABLE nicht automatisch mitkonvertiert. Sie müssen explizit neu erstellt werden. Ebenso werden temporäre Tabellen, die eine Anwendung zur Laufzeit anlegt, oft übersehen, wenn der zugrunde liegende Code den Charset hartcodiert.

Ein zweiter Fallstrick betrifft Fremdschlüssel-Beziehungen: Zwei Spalten mit unterschiedlichem Charset oder unterschiedlicher Collation können in MySQL keine gültige Fremdschlüssel-Beziehung eingehen, auch wenn die Datentypen sonst identisch sind. Während der Migration entstehen deshalb oft vorübergehend inkonsistente Zustände zwischen referenzierenden und referenzierten Tabellen, die zu einem Fehler beim nächsten ALTER TABLE führen, wenn nicht alle beteiligten Tabellen in derselben Migrationsrunde behandelt werden.

9. Zeichensätze und Collations im Vergleich

Die folgende Übersicht zeigt die wichtigsten Unterschiede zwischen dem veralteten utf8, dem empfohlenen utf8mb4 in seinen gängigen Collation-Varianten und dem reinen Binärvergleich.

Variante Max. Byte/Zeichen Emoji-fähig Empfehlung
utf8 (legacy) 3 Nein Migrieren
utf8mb4_unicode_ci 4 Ja Für MySQL 5.7 Legacy-Kompatibilität
utf8mb4_0900_ai_ci 4 Ja Standard für MySQL 8.0+
utf8mb4_bin 4 Ja Für exakte technische Vergleiche

Für neue Projekte ist die Entscheidung damit klar: utf8mb4 mit utf8mb4_0900_ai_ci als Standard-Collation für nutzerbezogene Textfelder, utf8mb4_bin gezielt für technische Identifikatoren, bei denen exakte Übereinstimmung gefordert ist. utf8 hat in einer neuen Installation keine Berechtigung mehr.

10. Zusammenfassung

Der Charset utf8 in MySQL ist ein historischer Kompromiss, der niemals vollständiges Unicode war und heute keine gültige Wahl mehr für neue Projekte darstellt. utf8mb4 schließt diese Lücke, verlangt aber Aufmerksamkeit bei Indexlängen, bei der Collation-Wahl und bei der durchgängigen Konfiguration von Server, Verbindung und Anwendung. Wer utf8mb4_0900_ai_ci als Standard setzt und technische Identifikatoren bewusst mit utf8mb4_bin versieht, vermeidet die häufigsten Sortier- und Vergleichsfehler.

Die Migration von utf8 zu utf8mb4 ist kein triviales Update, sondern ein Vorhaben, das Backups, Wartungsfenster und eine geordnete Reihenfolge über Views, Prozeduren und Fremdschlüssel-Beziehungen hinweg braucht. Der Aufwand lohnt sich, weil jede weitere Verzögerung das Risiko stillen Datenverlusts bei nutzergenerierten Inhalten erhöht.

Charset und Collation: utf8mb4 richtig einsetzen: Das Wichtigste auf einen Blick

utf8 vermeiden

Der MySQL-Charset utf8 kodiert maximal 3 Byte und kann kein vollständiges Unicode, insbesondere keine Emoji, abbilden.

utf8mb4 als Standard

4 Byte pro Zeichen, seit MySQL 8.0 Standard-Charset, deckt den gesamten Unicode-Bereich vollständig ab.

Collation bewusst wählen

utf8mb4_0900_ai_ci für Nutzertext, utf8mb4_bin für exakte technische Vergleiche wie Hashes und Tokens.

Indexlänge prüfen

4-Byte-Zeichen erhöhen die Indexschlüssellänge, moderne InnoDB-Formate mit 3072-Byte-Limit lösen das meist automatisch.

11. FAQ: Charset und Collation utf8mb4

1Warum ist utf8 kein echtes Unicode?
Maximal drei Byte pro Zeichen, deshalb können 4-Byte-Zeichen wie Emoji nicht gespeichert werden.
2Was ist der Unterschied zwischen Charset und Collation?
Charset speichert Zeichen als Bytes, Collation regelt Vergleich und Sortierung dieser Zeichen.
3unicode_ci oder 0900_ai_ci?
0900_ai_ci für neue MySQL-8-Installationen, präziser und performanter. unicode_ci nur für 5.7-Kompatibilität.
4Was bedeutet Specified key was too long?
Der Indexschlüssel überschreitet das InnoDB-Byte-Limit, meist bei altem Dateiformat nach Wechsel zu utf8mb4.
5Wie migriere ich eine Tabelle zu utf8mb4?
Mit ALTER TABLE ... CONVERT TO CHARACTER SET utf8mb4, konvertiert Tabelle und Spalten in einem Schritt.
6Warum bleibt Mojibake nach der Migration bestehen?
Meist fehlt SET NAMES utf8mb4 auf Verbindungsebene, der Client sendet Daten dann im falschen Charset.
7Werden Views automatisch mitkonvertiert?
Nein, Views, Prozeduren und Trigger müssen nach der Tabellenmigration explizit neu erstellt werden.
8Wann utf8mb4_bin statt ci-Collation?
Bei technischen Identifikatoren wie Hashes oder Tokens, wenn exakter Byte-Vergleich benötigt wird.
9Fremdschlüssel mit unterschiedlicher Collation?
Nicht möglich, Charset und Collation müssen bei Fremdschlüssel-Beziehungen übereinstimmen.
10Ist utf8mb4 langsamer als utf8?
Vernachlässigbar. 0900_ai_ci ist sogar performanter als die ältere unicode_ci-Collation.