UTF-8 und Emojis đđđ
Was viele nicht wissen: utf8
in MySQL ist nicht das "wahre" UTF-8. Es ist nur ein Alias fĂŒr utf8mb3
und kann daher nur bis zu drei Byte pro Zeichen speichern. Das fĂŒhrt zu Problemen mit Emojis und vielen Sonderzeichen, die bis zu vier Byte benötigen.
Inhaltsverzeichnis
Die UTF-8-Falle bei MySQL/MariaDB
Unicode, die Grundlage moderner Textkodierung, sollte eigentlich eine einfache Sache sein. Doch im Kontext von Datenbanken, insbesondere bei MySQL und MariaDB, kann die Wahl des richtigen Zeichensatzes zu Verwirrung fĂŒhren. HĂ€ufig stösst man auf Begriffe wie utf8
, utf8mb3
und utf8mb4
.
In diesem Beitrag möchte ich klÀren, warum utf8
und utf8mb3
dasselbe sind und warum die ausschliessliche Verwendung von utf8mb4
unerlÀsslich ist. Ausserdem werfe ich einen genaueren Blick auf die Unterschiede zwischen den beiden gÀngigen Sortierregeln utf8mb4_general_ci
und utf8mb4_unicode_ci
.
Daten wurden nicht korrekt entschlĂŒsselt
KĂŒrzlich habe ich mich bei unserem Eigenprojekt onlyforme mit der verschlĂŒsselten Speicherung von TagebucheintrĂ€gen befasst. Ich konnte die BinĂ€rdaten problemlos verschlĂŒsseln und in der Datenbank speichern. Die anschliessende EntschlĂŒsselung beim Auslesen der Daten ist dann jedoch fehlgeschlagen. Nach lĂ€ngerer Suche konnte ich die Ursache auf den von mir gewĂ€hlten Zeichensatz utf8
fĂŒr die Datenbank-Verbindung eingrenzen.
Gelöst wurde das Problem nach langer Suche durch die einfache ErgÀnzung von utf8
mit mb4
: https://github.com/Actra-AG/framework/commit/784bf61302362aa05c7ff07ee371c5dc9c26e681.
Der Unterschied zwischen utf8
/utf8mb3
und utf8mb4
Der Unterschied zwischen utf8
(Alias zu utf8mb3
) und utf8mb4
bei ZeichensĂ€tzen in MariaDB (und MySQl, da sie historisch eng verwandt sind) ist ein wichtiger Punkt, der oft zu Verwirrung und Datenverlust fĂŒhren kann.
Merkmal | utf8 /utf8mb3 |
utf8mb4 |
---|---|---|
Max. Bytes pro Zeichen | 3 Bytes | 4 Bytes |
Unicode-Abdeckung | BMP (Basic Multilingual Plane) | BMP, SMP (Supplementary Multilingual Plane) |
Emojis/Sonderzeichen | Nicht unterstĂŒtzt | Voll unterstĂŒtzt |
Bezeichnung | Historische, unvollstÀndige UTF-8-Alias utf8mb3 |
Echte, vollstÀndige UTF-8-Implementierung |
Empfehlung | Nicht mehr verwenden | Immer verwenden fĂŒr neue Projekte |
utf8
/utf8mb3
- Die alte/unvollstÀndige Implementierung in MariaDB/MySQL
utf8mb3
unterstĂŒtzt nur Zeichen, die bis zu 3 Bytes pro Zeichen benötigen. Es deckt nur die Basic Multilingual Plane (BMP) von Unicode ab. Dies beinhaltet die meisten gĂ€ngigen Zeichen fĂŒr europĂ€ische Sprachen, viele asiatische Sprachen (aber nicht alle) und grundlegende Symbole. Es können keine Zeichen gespeichert werden, die mehr als 3 Bytes benötigen. Dies sind insbesondere Emojis, seltene chinesische, japanische oder koreanische (CJK) Zeichen, bestimmte mathematische Symbole, spezielle musikalische Noten und historische Schriften.
Beim Versuch, ein 4-Byte-Zeichen in einer Spalte mit utf8-Charset zu speichern, kann dies zu Fehlern (z.B. "Incorrect string value: ...") oder Datenverlust (das Zeichen wird stillschweigend abgeschnitten oder in ein Fragezeichen umgewandelt) fĂŒhren.
Der Grund, warum MySQL/MariaDB dieses utf8
einfĂŒhrte, war, dass UTF-8 ursprĂŒnglich bis zu 4 Bytes pro Zeichen vorsah, aber zum Zeitpunkt der Implementierung die meisten verwendeten Zeichen nur bis zu 3 Bytes benötigten und man Speicherplatz sparen wollte. Die Bezeichnung utf8
ist daher irrefĂŒhrend, da es keine vollstĂ€ndige UTF8-Implementierung ist.
utf8mb4
- Die vollstÀndige UTF-8-Implementierung
utf8mb4
unterstĂŒtzt Zeichen, die bis zu 4 Bytes pro Zeichen benötigen. Es deckt den gesamten Unicode-Zeichensatz ab. Das bedeutet, es kann alle gĂŒltigen Unicode-Zeichen speichern, einschliesslich derer ausserhalb der BMP. utf8mb4
ist die echte und vollstÀndige Implementierung des UTF-8-Standards in MariaDB/MYSQL. Es ist vollstÀndig abwÀrtskompatibel mit utf8
. Das heisst, alle Zeichen, die in utf8
gespeichert werden können, können auch in utf8mb4
gespeichert werden, und sie nehmen denselben Speicherplatz ein. Der zusÀtzliche Platzbedarf tritt nur auf, wenn tatsÀchlich 4-Byte-Zeichen gespeichert werden.
Warum ist utf8mb4
heute der Standard und die Empfehlung?
Emojis sind heutzutage allgegenwÀrtig in der Kommunikation und in Webanwendungen. Ohne utf8mb4
können sie nicht korrekt gespeichert werden. FĂŒr Anwendungen, die ein globales Publikum ansprechen und verschiedene Sprachen und Skripte unterstĂŒtzen mĂŒssen, ist utf8mb4
unerlÀsslich. Da der Unicode-Standard stÀndig erweitert wird, stellt utf8mb4
sicher, dass die Datenbank auch zukĂŒnftige Zeichen verarbeiten kann. Der geringfĂŒgige Anstieg des Speicherplatzbedarfs fĂŒr 4-Byte-Zeichen ist in der Regel vernachlĂ€ssigbar im Vergleich zu den Vorteilen der vollstĂ€ndigen Unicode-UnterstĂŒtzung.
FĂŒr alle neuen Projekte in MariaDB oder MySQL sollte immer utf8mb4
als Zeichensatz verwendet werden. Sowohl auf Datenbank-, Tablelen- als auch auf Spaltenebene (wenn sie nicht die Standardwerte nutzen). Auch die Anwendungen (PHP, etc.) sollten ebenfalls utf8mb4
als Verbindungs-Charset verwenden.
Bei Àlteren Projekten mit utf8
/utf8mb3
sollte eine Migration zu utf8mb4
durchgefĂŒhrt werden, um auch die Speicherung von Emojis und anderen 4-Byte-Zeichen zu ermöglichen.
Der feine Unterschied zwischen utf8mb4_general_ci
vs. utf8mb4_unicode_ci
Nachdem wir nun wissen, dass utf8mb4
die richtige Wahl fĂŒr unseren Zeichensatz ist, stellt sich die nĂ€chste Frage: Welches Collation (Sortierregel) sollen wir wĂ€hlen? Die beiden gĂ€ngigsten Optionen sind utf8mb4_general_ci
vs. utf8mb4_unicode_ci
. Obwohl sie auf den ersten Blick Àhnliche Ergebnisse liefern, gibt es entscheidende Unterschiede in puncto PrÀzision und Performance.
Collation | Vorteile | Nachteile |
---|---|---|
utf8mb4_general_ci |
Ideal fĂŒr Anwendungen, bei denen die Geschwindigkeit von Such- und SortiervorgĂ€ngen kritisch ist. Benötigt weniger Systemressourcen. | Kann bei bestimmten Sprachen zu falschen Sortierungen fĂŒhren. So werden beispielsweise in der deutschen Sprache Umlaute (Ă€, ö, ĂŒ) oft wie ihre Grundzeichen (a, o, u) behandelt, was zu ungenauen Sortierungen fĂŒhren kann. Auch bei manchen asiatischen oder osteuropĂ€ischen Sprachen ist die Sortierung nicht immer korrekt. Sie hĂ€lt sich nicht vollstĂ€ndig an die strengen Regeln des Unicode Collation Algorithms (UCA). |
utf8mb4_unicode_ci |
HĂ€lt sich an die globalen Unicode-Standards, was eine sprachĂŒbergreifend korrekte Sortierung gewĂ€hrleistet. FĂŒr die deutsche Sprache bedeutet dies, dass "Ă€" und "Ă" als "ae" sortiert werden, was in vielen FĂ€llen dem gewĂŒnschten Verhalten entspricht. Deckt eine breitere Palette an Zeichen und deren Regeln ab. | Die komplexeren Vergleichsregeln können zu einer minimal geringeren Performance bei sehr grossen Datenmengen fĂŒhren. Dieser Unterschied ist in den meisten Anwendungen jedoch vernachlĂ€ssigbar. Benötigt etwas mehr Speicherplatz fĂŒr Indizes. |
Was ist Collation?
Collation definiert die Regeln fĂŒr den Vergleich und die Sortierung von Zeichen einer Zeichenfolge. Es legt fest, ob "A" und "a" als gleich gelten, wie Umlaute sortiert werden (Ă€, ö, ĂŒ) und wie Sonderzeichen behandelt werden. Das Suffix _ci
in beiden Collation-Namen steht fĂŒr case-insensitive, was bedeutet, dass bei Vergleichen Gross- und Kleinschreibung ignoriert wird.
utf8mb4_general_ci
: Schnell, aber weniger genau
Die Collation utf8mb4_general_ci
ist die Ă€ltere und einfachere der beiden. Sie ist in der Regel schneller und benötigt weniger Speicherplatz fĂŒr die Indizierung. Der Grund dafĂŒr ist, dass sie einfache, binĂ€re Regeln fĂŒr den Zeichenvergleich verwendet und einige spezifische Sortierregeln, die in bestimmten Sprachen notwendig sind, weglĂ€sst.
Empfehlung: Deine Wahl der Collation
FĂŒr die meisten modernen Webanwendungen, die eine breite SprachunterstĂŒtzung benötigen und Wert auf korrekte Such- und Sortierergebnisse legen, ist utf8mb4_unicode_ci
die klare Empfehlung. Der geringe Performance-Unterschied ist in den allermeisten FĂ€llen nicht spĂŒrbar und die Vorteile der prĂ€zisen und korrekten Sortierung ĂŒberwiegen bei weitem.
utf8mb4_general_ci
sollte nur in spezifischen Nischen verwendet werden, wo maximale Geschwindigkeit absolut kritisch ist und die EinschrÀnkung in der Sortierung bewusst in Kauf genommen werden kann. Andernfalls ist utf8mb4_unicode_ci
die sichere und zukunftstrÀchtigere Wahl.
Kontaktieren Sie uns
Benötigen Sie UnterstĂŒtzung bei der Programmierung in PHP? Gerne unterstĂŒtzen wir Sie mit unserer individuellen Webentwicklung.
Kontaktieren Sie uns fĂŒr eine unverbindliche Beratung!