MySQL の文字コードと照合順序
MySQL で文字列データを正しく扱うには、文字コード(キャラクタセット)と照合順序(コレーション)の設定が欠かせません。文字化けや予期しないソート結果の多くは、この設定の不備が原因です。
文字コードとは
文字コードは、文字をどのバイト列で表現するかを定義するルールです。MySQL では「キャラクタセット(CHARACTER SET / CHARSET)」と呼びます。
UTF-8 の完全な実装で、絵文字を含むすべての Unicode 文字を格納できます。MySQL 8.0 ではデフォルトのキャラクタセットです。1文字あたり最大4バイトを使用します。
MySQL 独自の UTF-8 実装で、1文字あたり最大3バイトまでしか扱えません。4バイト文字(絵文字、一部の漢字)を格納できないため、新規プロジェクトでは使用すべきではありません。
MySQL の utf8 は厳密には UTF-8 ではないという歴史的な事情があります。MySQL 8.0 で utf8mb4 がデフォルトになったことで、この混乱は解消されつつありますが、古いシステムでは依然として utf8(utf8mb3)が使われていることがあります。
照合順序とは
照合順序は、文字列の比較やソートの方法を定義するルールです。同じキャラクタセットでも、照合順序によって「AとaがAが等しいか」「はとハは等しいか」が変わります。
-- 照合順序の確認
SHOW VARIABLES LIKE 'collation%';
-- テーブルの照合順序を指定
CREATE TABLE messages (
id INT AUTO_INCREMENT PRIMARY KEY,
content VARCHAR(500) NOT NULL
) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;主要な照合順序の違い
| 照合順序 | 特徴 | 用途 |
|---|---|---|
| utf8mb4_general_ci | 高速だが比較精度が低い | レガシーシステム |
| utf8mb4_unicode_ci | Unicode 標準の比較 | 一般的な用途 |
| utf8mb4_0900_ai_ci | MySQL 8.0 デフォルト | 新規プロジェクト推奨 |
名前の末尾にある ci は Case Insensitive(大文字小文字を区別しない)、ai は Accent Insensitive(アクセント記号を区別しない)を意味します。
‘Alice’ = ‘alice’ が TRUE になる。ユーザー名やメールアドレスの検索には便利だが、パスワードハッシュのようなバイナリ比較が必要な場面では不適切。
‘Alice’ ≠ ‘alice’ となる。厳密な一致が必要なカラムに使う。BINARY 属性を付けるか、_bin 照合順序を指定する。
設定の4つのレベル
文字コードと照合順序は、サーバー → データベース → テーブル → カラムの4段階で設定でき、下位の設定が上位を上書きします。
-- データベースレベル
CREATE DATABASE myapp
CHARACTER SET utf8mb4
COLLATE utf8mb4_0900_ai_ci;
-- テーブルレベル(データベースの設定を継承)
CREATE TABLE users (
id INT AUTO_INCREMENT PRIMARY KEY,
name VARCHAR(100) NOT NULL,
-- カラムレベルで個別に指定も可能
code VARCHAR(20) NOT NULL COLLATE utf8mb4_bin
);基本的にはデータベースレベルで utf8mb4 と utf8mb4_0900_ai_ci(MySQL 8.0 の場合)を設定し、厳密な比較が必要なカラムだけ個別に _bin を指定するのがシンプルな運用方針です。
文字コード関連のトラブル
文字化けが起きる場合は、クライアント接続の文字コード設定が原因であることが多いです。テーブルが utf8mb4 でも、接続が latin1 だと文字化けします。接続時に SET NAMES utf8mb4 を実行するか、アプリケーションの接続文字列で charset=utf8mb4 を指定して、すべての経路で文字コードを統一することが重要です。



