15%

15% auf alle Hosting-Dienste sparen

Teste deine Fähigkeiten und erhalte Rabatt auf jeden Hosting-Plan

Benutze den Code:

Skills
Anfangen
08.10.2024

utf8 vs utf8mb4 in MySQL: Der vollständige technische Leitfaden

MySQL's utf8-Zeichensatz ist eine Fehlbezeichnung – er ist keine echte UTF-8-Implementierung. Er kodiert Zeichen mit nur 1 bis 3 Bytes, was bedeutet, dass er jeden Unicode-Codepunkt oberhalb von U+FFFF stillschweigend verwirft oder ablehnt, einschließlich aller Emojis und eines erheblichen Teils der ergänzenden CJK-Zeichen. utf8mb4 ist MySQLs korrekte, vollständige UTF-8-Implementierung, die 1 bis 4 Bytes pro Zeichen und den vollständigen Unicode-Bereich unterstützt. Für jede Produktionsdatenbank, die nach 2010 erstellt wurde, ist utf8mb4 die einzig vertretbare Wahl.

Dieser Leitfaden erklärt genau, warum dieser Unterschied wichtig ist, wo das ursprüngliche utf8-Design schiefgelaufen ist, wie man sicher migriert und wie man MySQL korrekt auf Server-, Datenbank-, Tabellen- und Verbindungsebene konfiguriert.

Das Kernproblem: Warum MySQLs utf8 von Grund auf fehlerhaft ist

Der UTF-8-Kodierungsstandard (RFC 3629) definiert ein Schema variabler Breite, das 1 bis 4 Bytes verwendet, um jeden gültigen Unicode-Codepunkt darzustellen – über 1,1 Millionen mögliche Zeichen. Als MySQL seinen `utf8`-Zeichensatz in Version 4.1 einführte, wurde die Implementierung absichtlich auf 3 Bytes pro Zeichen begrenzt. Dies war eine bewusste technische Abkürzung, kein Versehen.

Zu dieser Zeit legte das InnoDB-Zeilenformat ein Limit von 767 Bytes für Index-Schlüsselpräfixe fest. Die Unterstützung von 4-Byte-Zeichen hätte die maximale indizierte Präfixlänge für `VARCHAR`-Spalten reduziert und Index-Kompatibilitätsprobleme verursacht. Die 3-Byte-Begrenzung war ein pragmatischer Workaround, der zu einer langfristigen Belastung wurde.

Die praktische Konsequenz: Jeder Unicode-Codepunkt in der Supplementary Multilingual Plane (SMP) – Codepunkte U+10000 und höher – kann nicht in einer `utf8`-Spalte gespeichert werden. Dazu gehören:

  • Alle Standard-Emojis (U+1F600 und darüber hinaus)
  • Mathematische alphanumerische Symbole (U+1D400–U+1D7FF)
  • Musiknotationssymbole
  • Historische Schriften wie Linear B, Gotisch und Keilschrift
  • Ergänzende CJK Unified Ideographs (U+20000–U+2A6DF)
  • Bestimmte Währungssymbole und technische Operatoren, die in neueren Unicode-Versionen hinzugefügt wurden

Wenn eine Anwendung versucht, ein 4-Byte-Zeichen in eine `utf8`-Spalte einzufügen, gibt MySQL entweder einen `Incorrect string value`-Fehler zurück oder, wenn `sql_mode` permissiv ist, schneidet die Daten stillschweigend ab. Stille Abschneidung ist wohl das gefährlichere Ergebnis – Ihre Anwendung erhält keinen Fehler, aber Ihre Daten sind beschädigt.

utf8mb4: Die korrekte Implementierung

MySQL führte utf8mb4 in Version 5.5.3 (veröffentlicht 2010) speziell ein, um diesen Mangel zu beheben. Das Suffix `mb4` steht für „multi-byte, 4 bytes maximum”. Es ist eine strikte Obermenge von `utf8` – jedes in `utf8` darstellbare Zeichen ist identisch in `utf8mb4` darstellbar. Bei der Migration von `utf8` zu `utf8mb4` gehen keine Daten verloren.

utf8mb4 entspricht direkt dem RFC 3629 UTF-8-Standard. Es verarbeitet den vollständigen Unicode-Coderaum von U+0000 bis U+10FFFF ohne Einschränkungen.

utf8 vs utf8mb4: Funktionsvergleich

Merkmalutf8 (MySQL)utf8mb4
Bytes pro Zeichen1–31–4
Unicode-AbdeckungNur BMP (U+0000–U+FFFF)Vollständig (U+0000–U+10FFFF)
Emoji-UnterstützungNeinJa
Ergänzendes CJKNeinJa
RFC 3629-konformNeinJa
Max. Indexpräfix (InnoDB, 4KB-Seiten)767 Bytes767 Bytes (191 Zeichen)
Max. Indexpräfix (innodb_large_prefix)3072 Bytes3072 Bytes (768 Zeichen)
Speicher-Overhead vs. latin1Identisch für ASCIIIdentisch für ASCII
Empfohlen für neue ProjekteNeinJa
Eingeführt in MySQL-Version4.15.5.3

Kollationsoptionen innerhalb von utf8mb4

Die Auswahl von utf8mb4 als Zeichensatz ist nur die halbe Entscheidung. Die Kollation bestimmt, wie Zeichenketten verglichen, sortiert und indiziert werden. Die falsche Kollation verursacht subtiles, schwer zu debuggendes Abfrageverhalten.

utf8mb4_unicode_ci

Basiert auf dem Unicode Collation Algorithm (UCA). Verarbeitet sprachspezifische Sortierregeln korrekt. Etwas langsamer als `utf8mb4_general_ci` aufgrund komplexerer Vergleichslogik, aber der Leistungsunterschied ist auf moderner Hardware vernachlässigbar.

utf8mb4_general_ci

Eine vereinfachte Kollation, die UCA nicht vollständig implementiert. In Benchmarks der frühen 2010er Jahre schneller, aber der Geschwindigkeitsvorteil ist auf aktuellen CPUs irrelevant. Sie behandelt einige Grenzfälle falsch – zum Beispiel behandelt sie bestimmte deutsche Zeichen als gleichwertig, obwohl sie es nicht sein sollten. Für neue Projekte vermeiden.

utf8mb4_0900_ai_ci

Verfügbar in MySQL 8.0+. Basiert auf Unicode 9.0 mit akzentunempfindlichem (`ai`) und groß-/kleinschreibungsunempfindlichem (`ci`) Vergleich. Dies ist der empfohlene Standard für MySQL 8.0 und höher. Er ist schneller als `utf8mb4_unicode_ci` und genauer.

utf8mb4_bin

Binärer Vergleich – groß-/kleinschreibungsempfindlich, akzentempfindlich, keine gebietsschemaspezifischen Regeln. Verwenden Sie diese Option, wenn Sie eine exakte Byte-Übereinstimmung benötigen, z. B. für Passwort-Hashes oder groß-/kleinschreibungsempfindliche Bezeichner.

Empfehlung: Verwenden Sie `utf8mb4_0900_ai_ci` auf MySQL 8.0+. Verwenden Sie `utf8mb4_unicode_ci` auf MySQL 5.7 und früher.

Speicher- und Index-Implikationen

Ein häufiges Problem bei der Migration von utf8 zu utf8mb4 ist der Speicher-Overhead. In der Praxis ist die Auswirkung minimal:

  • ASCII-Zeichen (U+0000–U+007F) belegen in beiden Kodierungen weiterhin genau 1 Byte.
  • Die meisten lateinischen, griechischen, kyrillischen, arabischen und hebräischen Zeichen belegen in beiden Kodierungen 2 Bytes.
  • CJK-Zeichen im BMP belegen in beiden Kodierungen 3 Bytes.
  • Nur ergänzende Zeichen (Emojis, ergänzendes CJK) benötigen 4 Bytes – und diese waren in utf8 schlicht nicht darstellbar.

Das eigentliche Index-Problem ist das 767-Byte-InnoDB-Indexpräfixlimit bei älteren Konfigurationen. Mit utf8mb4 bedeutet ein Worst-Case von 4 Bytes pro Zeichen, dass ein 191-Zeichen-`VARCHAR`-Indexpräfix die 767-Byte-Grenze erreicht. Mit `utf8` erlaubte dieselbe Grenze 255 Zeichen. Wenn Sie `VARCHAR(255)`-Spalten mit vollständigen Spaltenindizes haben, können während der Migration `Specified key was too long`-Fehler auftreten.

Lösungen:

  • Aktivieren Sie `innodb_large_prefix = ON` (MySQL 5.6/5.7), um das Limit auf 3072 Bytes zu erhöhen.
  • Verwenden Sie `ROW_FORMAT=DYNAMIC` oder `ROW_FORMAT=COMPRESSED` für betroffene Tabellen.
  • In MySQL 8.0 ist `innodb_large_prefix` standardmäßig aktiviert und der Parameter wurde entfernt.
  • Kürzen Sie Indexpräfixe: `INDEX (column(191))` statt `INDEX (column(255))`.

Dies ist der häufigste Migrationsfehler und derjenige, der in grundlegenden Anleitungen am häufigsten unzureichend dokumentiert ist.

So migrieren Sie eine MySQL-Datenbank von utf8 zu utf8mb4

Die Migration ist unkompliziert, erfordert aber Präzision. Das Überspringen einer Ebene – Server, Datenbank, Tabelle oder Verbindung – führt dazu, dass Ihre Anwendung stillschweigend auf die alte Kodierung zurückfällt.

Schritt 1: Datenbank sichern

Ändern Sie niemals die Zeichenkodierung einer Live-Datenbank ohne eine verifizierte Sicherung.

“`bash

mysqldump -u username -p –single-transaction –routines –triggers

database_name > database_backup_$(date +%F).sql

“`

Das Flag `–single-transaction` gewährleistet einen konsistenten Snapshot für InnoDB-Tabellen ohne Sperren. Speichern Sie die Sicherung an einem vom Datenbankserver getrennten Ort, bevor Sie fortfahren.

Schritt 2: MySQL-Serverkonfiguration aktualisieren

Bearbeiten Sie `/etc/mysql/my.cnf` oder `/etc/mysql/mysql.conf.d/mysqld.cnf` je nach Ihrer Distribution:

“`ini

[client]

default-character-set = utf8mb4

[mysql]

default-character-set = utf8mb4

[mysqld]

character-set-server = utf8mb4

collation-server = utf8mb4_unicode_ci

For MySQL 5.6/5.7 only — remove on MySQL 8.0

innodb_large_prefix = ON

innodb_file_format = Barracuda

innodb_file_per_table = ON

“`

MySQL neu starten:

“`bash

sudo systemctl restart mysql

“`

Schritt 3: Datenbank konvertieren

“`sql

ALTER DATABASE database_name

CHARACTER SET = utf8mb4

COLLATE = utf8mb4_unicode_ci;

“`

Schritt 4: Alle Tabellen konvertieren

Generieren und führen Sie `ALTER TABLE`-Anweisungen für jede Tabelle aus. Das manuelle Ausführen bei großen Schemas ist fehleranfällig. Verwenden Sie diese Abfrage, um die Anweisungen automatisch zu generieren:

“`sql

SELECT CONCAT(

'ALTER TABLE `', TABLE_NAME, '` CONVERT TO CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;'

)

FROM information_schema.TABLES

WHERE TABLE_SCHEMA = 'database_name'

AND TABLE_TYPE = 'BASE TABLE';

“`

Führen Sie jede generierte Anweisung aus. Die `CONVERT TO CHARACTER SET`-Syntax ändert sowohl den Tabellenstandard als auch alle vorhandenen Zeichenspalten in einem einzigen Vorgang.

Schritt 5: Indexlängenfehler beheben

Wenn Sie auf `Specified key was too long; max key length is 767 bytes` stoßen, identifizieren Sie den betroffenen Index:

“`sql

— Change full-column index to prefix index

ALTER TABLE table_name DROP INDEX index_name;

ALTER TABLE table_name ADD INDEX index_name (column_name(191));

“`

Bei WordPress-Datenbanken sind die `option_name`-Spalte der `wp_options`-Tabelle und die `meta_key`-Spalte von `wp_postmeta` häufige Quellen dieses Fehlers.

Schritt 6: Konvertierung überprüfen

“`sql

— Check server-level variables

SHOW VARIABLES LIKE 'character_set%';

SHOW VARIABLES LIKE 'collation%';

— Check a specific table

SHOW CREATE TABLE table_nameG

— Check all columns in a database

SELECT TABLE_NAME, COLUMN_NAME, CHARACTER_SET_NAME, COLLATION_NAME

FROM information_schema.COLUMNS

WHERE TABLE_SCHEMA = 'database_name'

AND DATA_TYPE IN ('char', 'varchar', 'text', 'tinytext', 'mediumtext', 'longtext');

“`

Jeder `CHARACTER_SET_NAME`-Wert sollte `utf8mb4` anzeigen.

Schritt 7: Anwendungsverbindungszeichenketten aktualisieren

Die Server- und Schema-Kodierung bedeutet nichts, wenn Ihre Anwendung mit dem falschen Zeichensatz verbindet. Die verbindungsebene Kodierung überschreibt den Serverstandard.

PHP (PDO):

“`php

$dsn = 'mysql:host=localhost;dbname=database_name;charset=utf8mb4';

$pdo = new PDO($dsn, $user, $pass, [

PDO::MYSQL_ATTR_INIT_COMMAND => "SET NAMES utf8mb4 COLLATE utf8mb4_unicode_ci"

]);

“`

PHP (MySQLi):

“`php

$mysqli = new mysqli('localhost', $user, $pass, $db);

$mysqli->set_charset('utf8mb4');

“`

Python (mysql-connector-python):

“`python

cnx = mysql.connector.connect(

host='localhost', user=user, password=pass,

database=db, charset='utf8mb4', collation='utf8mb4_unicode_ci'

)

“`

Node.js (mysql2):

“`javascript

const pool = mysql2.createPool({

host: 'localhost', user: user, password: pass,

database: db, charset: 'utf8mb4'

});

“`

Das Versäumnis, den Verbindungszeichensatz festzulegen, ist der häufigste Grund, warum Emojis nach einer vermeintlich vollständigen Migration immer noch nicht eingefügt werden können.

WordPress-spezifische Überlegungen

WordPress wird seit Version 4.2 (April 2015) standardmäßig mit utf8mb4 als Zeichensatz ausgeliefert. Wenn Sie eine WordPress-Installation auf einer älteren Datenbank betreiben, die nie migriert wurde, enthält die Datei `wp-config.php` möglicherweise noch:

“`php

define('DB_CHARSET', 'utf8');

“`

Ändern Sie dies in:

“`php

define('DB_CHARSET', 'utf8mb4');

define('DB_COLLATE', 'utf8mb4_unicode_ci');

“`

WordPress enthält auch eine integrierte Upgrade-Routine (`maybe_convert_table_to_utf8mb4()`), die bei Core-Updates ausgeführt wird. Diese Routine erfasst jedoch nicht immer jede Tabelle, insbesondere solche, die von Plugins erstellt wurden. Der oben beschriebene manuelle `ALTER TABLE`-Ansatz ist zuverlässiger.

In einer VPS Hosting-Umgebung mit Root-Zugriff können Sie diesen gesamten Prozess mit einem Shell-Skript automatisieren und als einmaligen Cron-Job planen, was Ihnen volle Kontrolle über Zeitplanung und Protokollierung gibt.

Leistungsüberlegungen

Der Leistungsunterschied zwischen utf8mb4 und utf8 ist für die überwiegende Mehrheit der Workloads vernachlässigbar:

  • Leseabfragen: Kein messbarer Unterschied für BMP-Zeichen. Ergänzende Zeichen benötigen ein zusätzliches Byte I/O, das durch Buffer-Pool-Caching absorbiert wird.
  • Schreibabfragen: Identisch für ASCII- und BMP-Inhalte. Geringfügig höher für ergänzende Zeichen.
  • Indexoperationen: Die reduzierte maximale Präfixlänge (191 vs. 255 Zeichen für vollbreite Indizes) kann Abfragepläne beeinflussen, wenn Sie vollständige Spaltenindizes auf langen `VARCHAR`-Spalten haben. Überprüfen Sie Ihre Indizes vor und nach der Migration.
  • Speicher: MySQL reserviert feste Puffer für Zeichenkettenoperationen basierend auf der maximalen Bytes pro Zeichen. Der Wechsel von utf8 (max. 3 Bytes) zu utf8mb4 (max. 4 Bytes) erhöht den für In-Memory-Sortierpuffer und temporäre Tabellen reservierten Speicher bei zeichenkettenintensiven Operationen um etwa 33%. Auf einem Dedicated Server mit ausreichend RAM ist dies unerheblich. In einer speicherbeschränkten gemeinsamen Umgebung überwachen Sie `sort_buffer_size` und `tmp_table_size` nach der Migration.

Wann utf8 noch akzeptabel ist

Es gibt eine begrenzte Anzahl legitimer Gründe, `utf8` beizubehalten:

  • Strikte Legacy-Kompatibilität: Eine Anwendung, die ein nicht mehr gewartetes ORM oder einen Datenbanktreiber verwendet, der keine 4-Byte-Zeichen verarbeiten kann. Dies ist ein technisches Schuldenproblem, kein Grund, utf8 auf unbestimmte Zeit beizubehalten.
  • Schreibgeschützte Archivdatenbanken: Wenn eine Datenbank nie neue Schreibvorgänge erhalten wird und die vorhandenen Daten keine ergänzenden Zeichen enthalten, fügt die Migration Risiken ohne Nutzen hinzu.
  • Harte Speicherbeschränkungen: In extremen Grenzfällen – eingebettete Systeme oder stark kapazitätsbeschränkte Umgebungen – könnte der marginale Speicherunterschied eine Rolle spielen. Dies gilt nicht für ein standardmäßiges Webhosting-Szenario.

In allen anderen Fällen ist utf8mb4 die richtige Wahl. Das Argument, dass utf8 Speicherplatz spart, ist technisch gesehen nur für ergänzende Zeichen wahr, die in utf8 ohnehin nicht darstellbar waren. Sie sparen keinen Platz für Daten, die Sie nicht speichern konnten.

Die richtige Hosting-Umgebung für MySQL utf8mb4 wählen

Eine ordnungsgemäße utf8mb4-Konfiguration erfordert Zugriff auf die MySQL-Serverkonfigurationsdatei (`my.cnf`). Dies schließt die meisten Shared-Hosting-Umgebungen aus, in denen Sie keine Variablen auf Serverebene ändern können.

Für vollständige Kontrolle über MySQL-Zeichenkodierung, Kollation, InnoDB-Einstellungen und Verbindungsparameter benötigen Sie entweder einen VPS Hosting-Plan mit Root-Zugriff oder einen Dedicated Server. Beide geben Ihnen direkten Zugriff auf `/etc/mysql/my.cnf`, die Möglichkeit, den MySQL-Dienst neu zu starten, und die Freiheit, `innodb_large_prefix`, `ROW_FORMAT` und andere Parameter zu konfigurieren, die den Erfolg der utf8mb4-Migration beeinflussen.

Wenn Sie mehrere Datenbanken oder Kundenseiten verwalten, bietet ein VPS mit cPanel eine grafische Oberfläche für die Datenbankverwaltung, während der zugrunde liegende Serverzugriff für die Zeichensatzkonfiguration erhalten bleibt. Für Teams, die Kommandozeilenflexibilität mit einem leichtgewichtigen Panel bevorzugen, bieten VPS Control Panels mehrere Alternativen, die für verschiedene Betriebsabläufe geeignet sind.

Für Projekte, die auch eine sichere Datenübertragung erfordern, stellt die Kombination Ihrer Datenbankmigration mit einem ordnungsgemäß konfigurierten SSL Certificate sicher, dass utf8mb4-kodierte Daten bei der Übertragung geschützt sind, nicht nur im Ruhezustand.

Technische Entscheidungs-Checkliste

Verwenden Sie diese Checkliste vor und nach jeder Migration von utf8 zu utf8mb4:

Vor der Migration:

  • [ ] Vollständige `mysqldump`-Sicherung verifiziert und wiederherstellbar
  • [ ] MySQL-Version bestätigt (5.5.3+ für utf8mb4 erforderlich)
  • [ ] `innodb_large_prefix`-Status überprüft (aktivieren, wenn auf MySQL 5.6/5.7)
  • [ ] Alle `VARCHAR(255)`-Spalten mit vollständigen Spaltenindizes identifiziert
  • [ ] Anwendungsverbindungs-Zeichensatz-Code überprüft und aktualisiert
  • [ ] Wartungsfenster für Produktionsdatenbanken geplant

Nach der Migration:

  • [ ] `SHOW VARIABLES LIKE 'character_set%'` zeigt `utf8mb4` auf Serverebene
  • [ ] `SHOW CREATE TABLE` bestätigt `utf8mb4` auf allen konvertierten Tabellen
  • [ ] `information_schema.COLUMNS`-Abfrage bestätigt keine verbleibenden `utf8`-Spalten
  • [ ] `SET NAMES utf8mb4` auf Anwendungsebene oder Äquivalent im Verbindungscode bestätigt
  • [ ] Emoji-Einfügungstest auf einer repräsentativen Tabelle bestanden
  • [ ] Abfrageleistungs-Baseline mit Metriken vor der Migration verglichen
  • [ ] Indexlängen verifiziert – keine stille Abschneidung langer indizierter Werte

FAQ

Führt die Migration von utf8 zu utf8mb4 zu Datenverlust?

Nein. utf8mb4 ist eine strikte Obermenge von MySQLs utf8. Jedes in einer utf8-Spalte gespeicherte Zeichen ist identisch in utf8mb4 darstellbar. Die Migration ist für vorhandene Daten nicht destruktiv. Das einzige Risiko sind Indexlängenfehler bei `VARCHAR(255)`-Spalten mit vollständigen Spaltenindizes, die durch Kürzen des Indexpräfixes behoben werden müssen.

Warum können Emojis nach der Konvertierung meiner Tabellen zu utf8mb4 immer noch nicht eingefügt werden?

Die häufigste Ursache ist der Anwendungsverbindungszeichensatz. Wenn Ihr PHP-, Python- oder Node.js-Code verbindet, ohne explizit `utf8mb4` anzugeben, verwendet MySQL den `character_set_client`-Standard des Servers für diese Sitzung. Fügen Sie `SET NAMES utf8mb4` oder den entsprechenden Zeichensatzparameter zu Ihrer Verbindungskonfiguration hinzu.

Was ist der Unterschied zwischen utf8mb4_unicode_ci und utf8mb4_0900_ai_ci?

`utf8mb4_unicode_ci` basiert auf Unicode 4.0-Kollationsregeln und ist die Standardwahl für MySQL 5.7. `utf8mb4_0900_ai_ci` basiert auf Unicode 9.0, ist der Standard in MySQL 8.0 und ist sowohl schneller als auch linguistisch genauer. Verwenden Sie `utf8mb4_0900_ai_ci` auf MySQL 8.0+ für neue Projekte.

Wird der Wechsel zu utf8mb4 meine Datenbankgröße erheblich vergrößern?

In der Praxis nein. ASCII- und die meisten BMP-Zeichen verwenden in beiden Kodierungen die gleiche Anzahl von Bytes. Nur ergänzende Zeichen (Emojis, ergänzendes CJK) verwenden 4 Bytes – und diese waren in utf8 vorher nicht darstellbar. Der Speicher-Overhead für Sortierpuffer erhöht sich bei zeichenkettenintensiven Operationen um etwa 33%, aber dies ist auf jedem modernen Server vernachlässigbar.

Kann ich utf8mb4 auf Shared Hosting konfigurieren?

Teilweise. Sie können den Zeichensatz auf Datenbank- und Tabellenebene mit SQL-`ALTER`-Anweisungen festlegen und den Zeichensatz in der Verbindungszeichenkette Ihrer Anwendung angeben. Sie können jedoch `my.cnf` nicht ändern oder MySQL auf Shared Hosting neu starten. Standardeinstellungen auf Serverebene bleiben unverändert, was bedeutet, dass neue Datenbanken, die über das Hosting-Panel erstellt werden, möglicherweise standardmäßig utf8 verwenden. Eine vollständige utf8mb4-Konfiguration erfordert einen VPS oder dedizierten Server mit Root-Zugriff.

15%

15% auf alle Hosting-Dienste sparen

Teste deine Fähigkeiten und erhalte Rabatt auf jeden Hosting-Plan

Benutze den Code:

Skills
Anfangen