てもとツール

2026-05-23

utf8mb4とは?絵文字保存とMySQL文字コード対応の基本を徹底解説!

utf8mb4はMySQLで4バイトのUTF-8文字(絵文字や一部の漢字)まで保存できる文字セットです。utf8との違い・絵文字保存の仕組み・切り替え時の注意点を整理して解説します。

この記事の要点

  • utf8mb4はMySQLで4バイトまでのUTF-8文字(絵文字を含む)を保存できる文字セット
  • MySQLのutf8は3バイトまでしか扱えない別物(実体はutf8mb3)
  • 絵文字は4バイトのためutf8カラムに保存すると途切れたり?になる
  • MySQL 8.0以降はutf8mb3が非推奨で、新規アプリはutf8mb4を選ぶのが推奨
  • 切り替え時は照合順序とインデックス長制限・接続側の文字コードを確認する

「問い合わせフォームに絵文字を入れたら本文が途中で消えた」「SNS から取り込んだ投稿の 🍣? になっていた」。こうした症状の多くは、MySQL の文字コード設定を utf8mb4 に切り替えるだけで解決します。

絵文字を含む投稿を扱う SNS・問い合わせフォーム・コメント欄を運営するなら、utf8mb4 の理解は欠かせません。正しく設定するだけでデータ損失を防げます。


utf8mb4 とは(一言で)

utf8mb4 は MySQL(および MariaDB)で扱える「本物の UTF-8」を表す文字セット名です。mb4 は「multibyte 4」の略で、1 文字あたり最大 4 バイトまでの UTF-8 を許容する、という意味があります。

utf8mb4 を使う」とは、テーブルやカラムの CHARACTER SETutf8mb4 に指定することです。たとえば次のように CREATE TABLE で指定します。

CREATE TABLE messages (
  id INT PRIMARY KEY AUTO_INCREMENT,
  body TEXT
) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;

これだけで、本文に絵文字を含む投稿も欠損なく保存できます。


MySQL の utf8 と utf8mb4 の違い

項目utf8(実体は utf8mb3utf8mb4
1 文字あたりの最大バイト数3 バイト4 バイト
保存できる Unicode の範囲基本多言語面(BMP, U+0000〜U+FFFF)のみBMP + 追加面(U+10000〜U+10FFFF)
絵文字(😀 など)の保存できないできる
一部の漢字(𠮷・𩸽 など)の保存できないできる
MySQL 8.0 での扱い非推奨(将来削除予定)推奨

MySQL における utf8 は歴史的な経緯で「3 バイト UTF-8」を意味する独自定義です。Web 標準の UTF-8(最大 4 バイト)とは別物で、これが初学者最大の混乱ポイントになっています。

Oracle 公式ドキュメントでも将来の変更が示唆されています。utf8mb3 のエイリアスである utf8 は、将来 utf8mb4 を指すよう変更される見込みです。

この名前のずれが原因で生まれた有名なバグが「寿司ビール問題」です。utf8 カラムでは 🍣(寿司)と 🍺(ビール)が同じ値として扱われます。JOIN や UNIQUE 制約で「別物のはずなのに同一」と判定される事故が報告されました。


なぜ絵文字は 4 バイトになるのか

UTF-8 は Unicode のコードポイントを 1〜4 バイトで可変長エンコードする方式です。コードポイントの範囲によって必要なバイト数が決まります。

Unicode コードポイントUTF-8 バイト数
U+0000〜U+007F1 バイトA, 9, !
U+0080〜U+07FF2 バイトñ, ü, ギリシャ文字
U+0800〜U+FFFF3 バイト一般的な漢字、ひらがな、カタカナ
U+10000〜U+10FFFF4 バイト絵文字 😀、𠮷・𩸽 など追加面の漢字

絵文字の多くは U+1F300 以上に割り当てられており、4 バイトの領域に入ります。SNS の 🍣 寿司は U+1F363、バイト列は F0 9F 8D A3 の 4 バイトです。utf8 カラムに INSERT すると、4 バイト目以降が捨てられて空文字や ? になる挙動が起きます。

文字のバイト数や Unicode コードポイントを確認したいときは、文字数カウンター にテキストを貼り付けてください。UTF-8 バイト数・文字数・書記素クラスタ数を一度に確認できます。


切り替えるときの注意点

1. 照合順序(COLLATION)の選択

utf8mb4 には複数の照合順序があります。代表的なものは以下の 3 つです。

  • utf8mb4_general_ci: 軽量だが言語ごとの並び順がやや荒い
  • utf8mb4_unicode_ci: Unicode の正式な並び順に従う(精度が高い)
  • utf8mb4_0900_ai_ci: MySQL 8.0 以降の最新規格。デフォルトとして推奨

MySQL 8.0 系なら utf8mb4_0900_ai_ci が推奨です。互換性重視なら utf8mb4_unicode_ci を選ぶのが無難です。

2. インデックス長制限

MySQL 5.6 以前の InnoDB は インデックスのキー長が 767 バイト に制限されていました。utf8mb4 は 1 文字 4 バイトのため、VARCHAR(255) のインデックスは 1020 バイトになります。これは 767 バイトの制限を超えます。

対応策は以下の通りです。

  • MySQL 5.7 以降にアップグレードし、innodb_large_prefix = ONROW_FORMAT=DYNAMIC または COMPRESSED を有効化(5.7.7 以降は既定で有効)
  • カラム長を VARCHAR(191) 以下にする(191 × 4 = 764 で 767 以内に収まる)

3. 既存テーブルの変換

既にデータが入っているテーブルを utf8mb4 に切り替えるときは、ALTER TABLE を流します。

ALTER DATABASE mydb CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
ALTER TABLE messages
  CONVERT TO CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;

大規模テーブルでは、コンバート中にロックがかかる場合があります。メンテナンス時間を確保するか、pt-online-schema-change などのオンライン DDL ツールを検討してください。

4. 接続側の文字コード

接続側でも SET NAMES utf8mb4 を発行するか、接続文字列に charset=utf8mb4 を含める必要があります。サーバ側だけ切り替えても、接続が utf8 のままだと絵文字が ? になります。


文字数とバイト数を確認する方法

ブラウザでテキストのバイト数を確認するには、TextEncoder を使う方法が確実です。

const text = '🍣 寿司';
const bytes = new TextEncoder().encode(text);
console.log(text.length);   // 5(UTF-16 のコード単位数)
console.log(bytes.length);  // 11(UTF-8 のバイト数: 4 + 1 + 3 + 3)

String.prototype.length は UTF-16 のコード単位数を返します。絵文字 1 文字でも length === 2 です。VARCHAR(N) の N が何バイトに相当するかを正確に見積もるには、UTF-8 バイト数で考える必要があります。

手元で素早く確認したいときは 文字数カウンター を使うとブラウザだけで集計できます。バイト数・文字数・書記素クラスタの数を同時に出すので、VARCHAR の容量設計やフォームのバリデーション設計に役立ちます。


使用例

たとえば、問い合わせフォームで「ありがとう😊」と送信したログが、DB 上で「ありがとう」と切れていた場面を考えます。body カラムが utf8 のままで、絵文字 😊 の 4 バイト目が捨てられているケースが多めです。utf8mb4 への切り替えと接続側の charset=utf8mb4 指定で、絵文字を含むメッセージも欠損なく保存できます。


まとめ

  • utf8mb4 を最初から選んでおけば、絵文字や追加面の漢字を気にせずに保存できる
  • 既存システムで utf8 を使っているなら、ALTER TABLEutf8mb4 に変換しデータ損失リスクを下げる
  • 切り替え時はインデックス長制限と照合順序、接続側の文字コードを確認する
  • 文字数とバイト数の差は 文字数カウンター で把握しておくと、フォームやカラム設計のミスを減らせる

絵文字に対応した SNS・問い合わせフォーム・コメント欄を運営するなら、utf8mb4 は実質的に必須の選択肢です。文字コードの扱いに悩むことがあれば、Base64で日本語が文字化けする理由とUTF-8 もあわせて参照してください。Web の文字コード周りの全体像をつかみやすくなります。