MySQL では UTF-8 が推奨されないのはなぜですか?

MySQL では UTF-8 が推奨されないのはなぜですか?

最近、Rails 経由で「utf8」でエンコードされた UTF-8 文字列を MariaDB に保存しようとしたときに、奇妙なエラーが発生するというバグに遭遇しました。

不正な文字列値: '\xF0\x9F\x98\x83、行 1 の列 'summary'

クライアント、サーバー、データベースでは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 つの手順を実行する必要があります。

  1. コンピュータは「01000011」を読み取り、67 という数字を取得します。これは、67 が「01000011」としてエンコードされているためです。
  2. コンピュータは Unicode 文字セットで 67 を検索し、「C」を見つけます。

同様に:

  1. 私のコンピューターは、「C」を Unicode 文字セットの文字 67 にマッピングします。
  2. 私のコンピュータは 67 を「01000011」としてエンコードし、Web サーバーに送信します。

ほとんどすべての 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 年以降はそうではありません)。
CHAR 列のエンコードを「utf8」に設定します。
私の推測では、MySQL 開発者は、スペースと速度の両方でメリットのあるものを求めるユーザーを支援したかったのですが、「utf8」エンコーディングを台無しにしてしまったのです。

つまり、結果は勝者なしです。スペースと速度の両方のメリットを期待するユーザーは、「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

以下もご興味があるかもしれません:
  • MySQL データベースで UTF-8 エンコードを設定する方法
  • MySQL で UTF-8 エンコーディングを使用しないのはなぜですか?
  • MySQL GBK → UTF-8 エンコーディング変換

<<:  HTML チュートリアル、optgroup 要素の理解

>>:  Vueのライブ放送機能の詳しい説明

推薦する

Centos8 で yum を使用して mongodb 4.2 をインストールする方法

1. リポジトリファイルを作成するmongodb の公式インストール ドキュメントを参照し、次のスク...

モバイルデバイスでインラインスクロールを実装するための4つのソリューションの詳細な説明

ニーズの発見領域の一部のみスクロールでき、残りの部分は移動できない場合、どのような方法を使用しますか...

Vue における v-for のキーの一意性の詳細な説明

目次1. DOM の違い2. 同じレイヤーの同じタイプの要素にキー属性を追加する3. キーはインデッ...

MySQL 2級コンピュータ試験共通テストポイント 8つのMySQLデータベース設計最適化方法

MySQLデータベース設計の8つの最適化方法の詳細は次のとおりです。 1. 最も適切なフィールド属性...

テンプレートタグの使用方法の詳細な説明(Vue での使用方法の概要を含む)

目次1. HTML5のテンプレートタグ2. テンプレートタグ操作のプロパティとメソッド3. Vueの...

MySQL の挿入ステートメントの使用実体験

目次1. 挿入のいくつかの構文1-1. 通常の挿入文1-2. 挿入または更新1-3. 挿入または交換...

Windows で mysql-8.0.18-winx64 をインストールするチュートリアル (画像とテキスト付き)

1. インストールパッケージをダウンロードするインストール パッケージは次の場所にあります:参考:...

プロジェクトにおけるVue3のロジック抽出とフィールド表示についての簡単な説明

目次論理階層化異なる地域から事業を分離するこれを実行する利点このようなシナリオにどう対処するか最適化...

Linux での MongoDB のインストールと設定のチュートリアル

MongoDBインストールYumを使用してインストールすることを選択する1. repoファイルを作成...

ページング効果を実装するミニプログラム

この記事の例では、ページング効果表示を実現するためのミニプログラムの具体的なコードを参考までに共有し...

Linux スワップメモリ​​を拡張する方法

スワップ メモリとは、主に物理メモリが不足している場合に、システムがハード ディスク領域の一部をサー...

開発者がデータベースロックを詳細に理解する必要がある理由

1.ロックしますか? 1.1 ロックとは何ですか?ロックの本当の意味は、鍵またはコードで開くことがで...

モバイル端末の適応に関する簡単な説明

序文フロントエンド コードの記述では、「互換性」という言葉から逃れることはできません。過去の PC ...

ウェブデザインと制作の一般的な原則をまとめる

<br />関連記事: Web コンテンツ ページ作成に関する 9 つの実用的な提案、W...

MySQL と接続関連のタイムアウトの詳細な概要

MySQL と接続関連のタイムアウト序文:今日、同僚から、データ量が多いときに MySQL データベ...