Warum wird UTF-8 in MySQL nicht empfohlen?

Warum wird UTF-8 in MySQL nicht empfohlen?

Ich bin kürzlich auf einen Fehler gestoßen, als ich versuchte, eine UTF-8-Zeichenfolge in MariaDB, die in „utf8“ codiert war, über Rails zu speichern, und ich erhielt einen seltsamen Fehler:

Falscher Zeichenfolgenwert: '\xF0\x9F\x98\x83 für Spalte 'summary' in Zeile 1

Ich verwende UTF-8-Kodierung auf dem Client, dem Server und der Datenbank. Sogar die Zeichenfolge "

Der Kern des Problems besteht darin, dass „utf8“ von MySQL nicht wirklich echtes UTF-8 ist.

„utf8“ unterstützt nur bis zu drei Bytes pro Zeichen, während echtes UTF-8 bis zu vier Bytes pro Zeichen unterstützt.

MySQL hat diesen Fehler nie behoben und 2010 einen Zeichensatz namens „utf8mb4“ veröffentlicht, der dieses Problem umging.

Natürlich haben sie den neuen Zeichensatz nicht groß beworben (wahrscheinlich, weil ihnen dieser Fehler peinlich war), sodass Entwicklern im Internet weiterhin empfohlen wird, „utf8“ zu verwenden, aber diese Vorschläge sind falsch.

Eine kurze Zusammenfassung lautet wie folgt:

„utf8mb4“ von MySQL ist echtes „UTF-8“.

„utf8“ von MySQL ist eine „proprietäre Kodierung“, die nur wenige Unicode-Zeichen kodieren kann.

Ich möchte es hier klarstellen: Alle MySQL- und MariaDB-Benutzer, die „utf8“ verwenden, sollten zu „utf8mb4“ wechseln und nie wieder „utf8“ verwenden.

Was ist also Kodierung? Was ist UTF-8?

Wir alle wissen, dass Computer zum Speichern von Texten Nullen und Einsen verwenden. Wenn beispielsweise das Zeichen „C“ als „01000011“ gespeichert ist, muss der Computer zwei Schritte durchlaufen, um dieses Zeichen anzuzeigen:

  1. Der Computer liest „01000011“ und erhält die Zahl 67, da 67 als „01000011“ codiert ist.
  2. Der Computer sucht im Unicode-Zeichensatz nach 67 und findet „C“.

Ähnlich:

  1. Mein Computer ordnet „C“ dem Zeichen 67 im Unicode-Zeichensatz zu.
  2. Mein Computer kodiert 67 als „01000011“ und sendet es an den Webserver.

Fast alle Webanwendungen verwenden den Unicode-Zeichensatz, da es keinen Grund gibt, etwas anderes zu verwenden.

Der Unicode-Zeichensatz enthält Millionen von Zeichen. Die einfachste Kodierung ist UTF-32, das 32 Bit pro Zeichen verwendet. Dies ist am einfachsten, da Computer 32 Bit schon immer als Zahlen betrachtet haben und Computer hervorragend darin sind, Zahlen zu verarbeiten. Das Problem besteht jedoch darin, dass dadurch zu viel Platz verschwendet wird.

UTF-8 kann Platz sparen. In UTF-8 benötigt das Zeichen „C“ nur 8 Bit und einige ungewöhnliche Zeichen wie „“, benötigen 32 Bit. Andere Zeichen können 16 oder 24 Bit verwenden. Ein Artikel wie dieser nimmt, wenn er mit UTF-8 kodiert ist, nur etwa ein Viertel des Platzes von UTF-32 ein.

Der „utf8“-Zeichensatz von MySQL ist mit anderen Programmen nicht kompatibel. Was als „utf8“ bezeichnet wird, kann in Wirklichkeit ein Haufen sein...

Eine kurze Geschichte von MySQL

Warum sollten MySQL-Entwickler „utf8“ deaktivieren? Möglicherweise finden wir die Antwort im Commit-Protokoll.

MySQL unterstützt UTF-8 seit Version 4.1 im Jahr 2003, und der heute verwendete UTF-8-Standard (RFC 3629) kam später.

Der alte UTF-8-Standard (RFC 2279) unterstützt bis zu 6 Bytes pro Zeichen. Am 28. März 2002 verwendeten MySQL-Entwickler RFC 2279 in der ersten Vorabversion von MySQL 4.1.

Im September desselben Jahres nahmen sie eine Anpassung am MySQL-Quellcode vor: „UTF8 unterstützt jetzt nur noch Sequenzen von bis zu 3 Bytes.“

Wer hat diesen Code übermittelt? Warum hat er das getan? Die Antwort auf diese Frage ist unbekannt. Nach der Migration zu Git (MySQL verwendete ursprünglich BitKeeper) gingen viele Namen der Committer in der MySQL-Codebasis verloren. In der Mailingliste vom September 2003 finden sich keinerlei Hinweise, die diese Änderung erklären könnten.

Aber ich kann versuchen, es zu erraten.

Im Jahr 2002 traf MySQL eine Entscheidung: Wenn Benutzer sicherstellen können, dass jede Zeile der Datentabelle die gleiche Anzahl von Bytes verwendet, kann MySQL die Leistung erheblich verbessern. Hierzu muss der Benutzer die Textspalten als „CHAR“ definieren. Jede „CHAR“-Spalte hat immer die gleiche Anzahl an Zeichen. Wenn die Anzahl der eingefügten Zeichen kleiner als die definierte Zahl ist, füllt MySQL sie mit Leerzeichen auf. Wenn die Anzahl der eingefügten Zeichen die definierte Zahl überschreitet, wird der Überschuss abgeschnitten.

Als die MySQL-Entwickler erstmals mit UTF-8 experimentierten, verwendeten sie 6 Bytes pro Zeichen, CHAR(1) verwendete 6 Bytes, CHAR(2) verwendete 12 Bytes und so weiter.

Es sollte gesagt werden, dass ihr anfängliches Verhalten korrekt war, aber diese Version wurde leider nie veröffentlicht. Aber es steht im Dokument und wird weithin verbreitet. Jeder, der UTF-8 versteht, stimmt mit dem überein, was im Dokument steht.

Es ist jedoch klar, dass MySQL-Entwickler oder -Hersteller besorgt sind, dass Benutzer diese beiden Dinge tun könnten:

Definieren Sie die Spalte mit CHAR (heutzutage ist CHAR ein alter Hut, damals war es in MySQL schneller, seit 2005 ist das jedoch nicht mehr der Fall).
Stellen Sie die Kodierung der CHAR-Spalten auf „utf8“ ein.
Ich vermute, dass die MySQL-Entwickler den Benutzern helfen wollten, die eine Win-Win-Situation in puncto Speicherplatz und Geschwindigkeit wollten, aber sie haben die „utf8“-Kodierung vermasselt.

Das Ergebnis ist also kein Gewinner. Benutzer, die eine Win-Win-Situation in puncto Speicherplatz und Geschwindigkeit erwarten, stellen möglicherweise fest, dass sie bei der Verwendung von CHAR-Spalten mit „utf8“ tatsächlich mehr Speicherplatz verbrauchen als erwartet und langsamer sind als erwartet. Und Benutzer, die Korrektheit wollen, können bei Verwendung der „utf8“-Kodierung Zeichen wie „“ nicht speichern.

Nachdem dieser illegale Zeichensatz veröffentlicht wurde, konnte MySQL ihn nicht beheben, ohne alle Benutzer aufzufordern, ihre Datenbanken neu aufzubauen. Schließlich wurde MySQL 2010 als „utf8mb4“ neu veröffentlicht, um echtes UTF-8 zu unterstützen.

Warum macht diese Angelegenheit die Leute so verrückt? Wegen dieses Problems war ich eine ganze Woche lang verrückt. Ich wurde von „utf8“ getäuscht und habe viel Zeit damit verbracht, den Fehler zu finden. Aber ich bin definitiv nicht der Einzige, fast alle Artikel im Web behandeln „utf8“ als echtes UTF-8.

„utf8“ ist lediglich ein proprietärer Zeichensatz, der uns neue, noch ungelöste Probleme beschert.

Zusammenfassen

Wenn Sie MySQL oder MariaDB verwenden, verwenden Sie nicht die Kodierung „utf8“, sondern stattdessen „utf8mb4“. Hier finden Sie eine Anleitung zum Konvertieren einer vorhandenen Datenbank-Zeichenkodierung von „utf8“ in „utf8mb4“.

**Originaltext Englisch:**https://medium.com/@adamhooper/in-mysql-never-use-utf8-use-utf8mb4-11761243e434

Das könnte Sie auch interessieren:
  • So legen Sie die UTF-8-Kodierung in einer MySQL-Datenbank fest
  • Warum wird in MySQL keine UTF-8-Kodierung verwendet?
  • MySQL GBK → UTF-8-Kodierungskonvertierung

<<:  HTML-Tutorial: Das Optgroup-Element verstehen

>>:  Detaillierte Erläuterung der Live-Übertragungsfunktion von Vue

Artikel empfehlen

Zusammenfassung der Wissenspunkte zu MySQL-Index, Sperre und Transaktion

Dieser Artikel fasst die Wissenspunkte zu MySql-I...

Zusammenfassung der praktischen Erfahrungen zu HTML-Wissenspunkten

1. Das Tabellen-Tag ist Tabelle, tr ist Zeile, td ...

Einfacher Webseitencode, der im NetEase-Blog verwendet wird

So verwenden Sie den Code im NetEase-Blog: Melden...

Detaillierte Erklärung der verschiedenen Verwendungen von proxy_pass in nginx

Inhaltsverzeichnis Proxy-Weiterleitungsregeln Der...

Beispiel für die Verwendung der setInterval-Funktion in React

Dieser Artikel basiert auf der Windows 10-Systemu...

JS Leicht verständliche Funktion und Konstruktor

Inhaltsverzeichnis 1. Übersicht 1.1 Erstellen ein...

So lösen Sie das domänenübergreifende Front-End-Problem mithilfe des Nginx-Proxys

Vorwort Nginx (ausgesprochen „Engine X“) ist ein ...

CocosCreator allgemeines Framework-Design Ressourcenmanagement

Inhaltsverzeichnis Probleme mit der Ressourcenver...

Grundkenntnisse im Website-Design: Neulinge lesen bitte dies

Heutzutage beginnen viele Leute damit, Websites z...

Nginx-Stream-Konfigurationsproxy (Nginx TCP/UDP-Lastausgleich)

Auftakt Wir alle wissen, dass nginx ein hervorrag...