最近、Rails 経由で「utf8」でエンコードされた UTF-8 文字列を MariaDB に保存しようとしたときに、奇妙なエラーが発生するというバグに遭遇しました。
クライアント、サーバー、データベースではUTF-8エンコードを使用しています。文字列「 問題の核心は、MySQL の「utf8」が実際には真の UTF-8 ではないことです。 「utf8」は 1 文字あたり最大 3 バイトしかサポートしませんが、真の UTF-8 は 1 文字あたり最大 4 バイトをサポートします。 MySQL はこのバグを修正せず、2010 年にこの問題を回避する「utf8mb4」という文字セットをリリースしました。 もちろん、彼らは新しい文字セットを広く宣伝しませんでした (おそらくこのバグが彼らを恥ずかしい思いをさせたため)。そのため、開発者はインターネット上で依然として「utf8」を使用するようにアドバイスされていますが、これらの提案は間違っています。 簡単な要約は次のとおりです。 MySQL の「utf8mb4」は真の「UTF-8」です。 MySQL の「utf8」は、いくつかの Unicode 文字のみをエンコードできる「独自のエンコーディング」です。 ここで明確にしておきたいのは、「utf8」を使用しているすべての MySQL および MariaDB ユーザーは、「utf8mb4」に切り替えて、「utf8」を二度と使用しないでください。 では、エンコーディングとは何でしょうか? UTF-8とは何ですか?コンピューターがテキストを保存するために 0 と 1 を使用することは誰もが知っています。たとえば、文字「C」が「01000011」として保存されている場合、コンピューターはこの文字を表示するために次の 2 つの手順を実行する必要があります。
同様に:
ほとんどすべての Web アプリケーションでは、他の文字セットを使用する理由がないため、Unicode 文字セットが使用されます。 Unicode 文字セットには数百万の文字が含まれています。最も単純なエンコードは UTF-32 で、文字ごとに 32 ビットを使用します。コンピュータは常に 32 ビットを数値として認識しており、数値の計算が得意であるため、これを実行するのが最も簡単です。しかし問題は、これによってスペースが無駄になりすぎることです。 UTF-8 はスペースを節約できます。UTF-8 では、文字「C」に必要なのは 8 ビットだけですが、「」などの一部の一般的でない文字には 32 ビットが必要です。その他の文字では 16 ビットまたは 24 ビットが使用される場合があります。この記事のような記事は、UTF-8 を使用してエンコードすると、UTF-32 の約 4 分の 1 のスペースしか占有しません。 MySQL の「utf8」文字セットは他のプログラムと互換性がありません。「utf8」と呼ばれるものは、実際には... MySQLの簡単な歴史MySQL 開発者が「utf8」を無効にするのはなぜでしょうか?コミットログから答えが見つかるかもしれません。 MySQL は 2003 年のバージョン 4.1 から UTF-8 をサポートしており、現在使用されている UTF-8 標準 (RFC 3629) はその後登場しました。 古い UTF-8 標準 (RFC 2279) では、文字あたり最大 6 バイトがサポートされます。 2002 年 3 月 28 日、MySQL 開発者は MySQL 4.1 の最初のプレビュー リリースで RFC 2279 を使用しました。 同年 9 月、MySQL ソース コードに調整が加えられました。「UTF8 は現在、最大 3 バイトのシーケンスのみをサポートします。」 このコードを送信したのは誰ですか?彼はなぜそんなことをしたのですか?この質問に対する答えは不明です。 Git に移行した後 (MySQL は元々 BitKeeper を使用していました)、MySQL コードベースのコミッターの名前の多くが失われました。 2003 年 9 月のメーリング リストには、この変更を説明できる手がかりはありません。 しかし、推測してみることはできます。 2002 年に、MySQL は、ユーザーがデータ テーブルの各行で同じバイト数を使用することを保証できれば、MySQL のパフォーマンスを大幅に向上できるという決定を下しました。これを行うには、ユーザーはテキスト列を「CHAR」として定義する必要があります。各「CHAR」列の文字数は常に同じです。挿入された文字数が定義された数より少ない場合、MySQL はスペースで埋めます。挿入された文字数が定義された数を超える場合、超過分は切り捨てられます。 MySQL 開発者が最初に UTF-8 を試したとき、文字ごとに 6 バイトが使用され、CHAR(1) では 6 バイト、CHAR(2) では 12 バイトなどが使用されます。 当初の動作は正しかったと言えますが、残念ながらこのバージョンはリリースされていません。しかし、それは文書に書かれており、広く流布されています。UTF-8 を理解する人なら誰でも、文書に書かれていることに同意します。 しかし、MySQL の開発者やメーカーは、ユーザーが次の 2 つのことを行うのではないかと懸念していることは明らかです。 CHAR を使用して列を定義します (現在では CHAR は古い形式ですが、当時は MySQL の方が高速でしたが、2005 年以降はそうではありません)。 つまり、結果は勝者なしです。スペースと速度の両方のメリットを期待するユーザーは、「utf8」で CHAR 列を使用すると、実際には予想よりも多くのスペースが使用され、予想よりも遅くなることを感じる場合があります。また、正確性を求めるユーザーは、「utf8」エンコーディングを使用すると、「」のような文字を保存できません。 この不正な文字セットがリリースされた後、MySQL はすべてのユーザーにデータベースの再構築を依頼しない限り、これを修正できませんでした。最終的に、MySQL は真の UTF-8 をサポートするために 2010 年に「utf8mb4」として再リリースされました。 なぜこの問題は人々をそんなに狂わせるのでしょうか? この問題のせいで、私は丸一週間狂っていました。私は「utf8」に騙され、バグを見つけるのに多くの時間を費やしました。しかし、私だけがそう思っているわけではないことは確かです。Web 上のほぼすべての記事では、「utf8」を実際の UTF-8 として扱っています。 「utf8」は単なる独自の文字セットであり、解決されていない新たな問題を引き起こします。 要約するMySQL または MariaDB を使用している場合は、「utf8」エンコードを使用せず、代わりに「utf8mb4」を使用してください。ここでは、既存のデータベースの文字エンコードを「utf8」から「utf8mb4」に変換するためのガイドが提供されます。 **元の英語テキスト:**https://medium.com/@adamhooper/in-mysql-never-use-utf8-use-utf8mb4-11761243e434 以下もご興味があるかもしれません:
|
<<: HTML チュートリアル、optgroup 要素の理解
目次1. 基本1.参照2. 参照3. 参照4. 最適な使い方2. 詳細な1. なぜrefが必要なのか...
クリップパスの使用ポリゴン値は複数の座標点で構成されます。最初の値は x 方向、2 番目の値は y ...
導入近年、TypeScript を求める声がますます高まり、TypeScript はフロントエンドに...
1.コンテナに入った後 /etc/hosts を cat するコンテナ自体の IP アドレスと (-...
まずMySQLのインストールMySQLソフトウェアをダウンロードし、インストールパスを変更しますMy...
目次問題の説明原因分析解決問題の説明最近、奇妙な問い合わせを受けました。更新ステートメントはエラーな...
WeChatアプレットフォームの検証、参考までに具体的な内容は次のとおりです。プラグインWxVali...
1. サービス方法ファイアウォールのステータスを確認します。 [root@centos6 ~]# サ...
この記事では、一般的な MySQL ストレージ エンジンの機能と使用方法を例を使って説明します。ご参...
序文json を使用したことがある人なら、オブジェクトを文字列化してからバックエンドに送信するのが一...
CSS3 を使用して、クールなレーダースキャン画像を実現します。 コード上で直接: // インデック...
nGrinderとは何ですか? nGrinder は、スクリプトの作成、テストの実行、監視、結果レポ...
Count(*) または Count(1) または Count([column]) は、おそらく S...
1. 要素時間選択提出フォーマット変換例えば 2018年9月7日金曜日 00:00:00 GMT+0...
注:記事に誤りがある場合は、メッセージを残して指摘してください。ご協力ありがとうございます。名前名前...