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.

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!