MySQL8.0で突然「文字コード問題」が消えた理由
MySQLを長く触っていると、ある時期から妙な感覚になります。
「最近、文字化けトラブルを聞かなくなった」と感じた人もいるはずです。
実はこれ、偶然ではありません。
MySQL8.0でデフォルト文字コードが変更されたことが大きく影響しています。
そしてこの変更は、単なる改善ではなく「仕様の転換」に近いものです。
新規開発では恩恵になりますが、既存システムでは逆に混乱の原因にもなっています。
何が変わったのか
MySQL5.7までのデフォルトは次の設定でした。
- 文字コード:utf8
- 照合順序:utf8_general_ci
一方、MySQL8.0ではこうなりました。
- 文字コード:utf8mb4
- 照合順序:utf8mb4_0900_ai_ci
つまり、最初から4バイトUTF-8が使われます。
絵文字を保存できる設定が標準になりました。
SHOW VARIABLES LIKE 'character_set_server';
このコマンドを実行すると、バージョンによる違いが確認できます。
なぜこれが大きな変更なのか
一見すると「絵文字が保存できるようになった」だけに見えます。
しかし影響はそれだけではありません。
MySQLのデフォルト設定は、テーブル作成時に暗黙的に使われます。
CREATE TABLE users ( name VARCHAR(100) );
このSQLは、文字コードを指定していません。
つまりサーバのデフォルトを継承します。
5.7では3バイトUTF-8、
8.0では4バイトUTF-8になります。
同じSQLでも、データベースの中身が変わります。
移行時に起きる典型的な問題
MySQL8.0へアップグレードした直後、次の問題がよく起きます。
- アプリが接続できない
- テストだけ通らない
- インデックス作成エラー
- UNIQUE制約違反
原因は多くの場合、文字コードの不一致です。
特に多いのが「古いテーブル + 新しい接続設定」です。
- テーブル:utf8
- 接続:utf8mb4
この状態でデータを書き込むと、変換が発生します。
そして次のエラーが出ます。
- Incorrect string value
アプリのバグに見えますが、DBの仕様変更です。
COLLATIONも変わっている
見落とされがちですが、8.0では照合順序も変わりました。
utf8mb4_0900_ai_ci は新しいUnicodeルールに基づきます。
その結果、比較結果が変わります。
例えば次です。
- ß と ss
- 全角と半角
- アクセント付き文字
5.7では別扱いだったものが、同一扱いになる場合があります。
そのため次の現象が起きます。
- 重複エラーが出る
- ソート順が変わる
- JOIN結果が変わる
SQLを変えていないのに挙動が変わります。
なぜMySQLは変更したのか
背景は「SQL標準」と「Unicode」です。
旧来のutf8_general_ciは簡易比較でした。
高速ですが言語的に正確ではありません。
8.0はUnicodeの正式な照合規則に近づきました。
つまり、データベースとしての整合性を優先した変更です。
よくある誤解
「8.0にすれば文字コード問題は全部解決する」
これは半分だけ正しいです。
新規構築ではほぼ解決します。
しかし既存データには影響が出ます。
特に危険なのがバックアップのリストアです。
5.7のダンプを8.0に入れると、比較結果が変わる可能性があります。
アプリ側の想定とズレることがあります。
リスクと注意点
アップグレード前に確認すべき項目があります。
- テーブル文字コード
- カラム文字コード
- 接続文字コード
- COLLATION
これを確認せずに8.0へ移行すると、
「動くが挙動が変わる」状態になります。
このタイプの不具合は最も発見が遅れます。
さらにインデックス長の制限も影響します。
utf8mb4ではキー長が増えるため、旧設計では作成できないことがあります。
どう対応すべきか
単純なバージョンアップとして扱わないことが重要です。
文字コード移行として計画する必要があります。
具体的には次の順序が安全です。
- 既存テーブルをutf8mb4へ変換
- 接続設定を統一
- テストデータを日本語・絵文字で確認
- その後8.0へ移行
これを逆にすると原因調査が難しくなります。
この変更の本当の意味
MySQL8.0のデフォルト文字コード変更は、単なる便利機能ではありません。
「データベースは文字列を正しく扱うべき」という方向への転換です。
これまでのMySQLは「多少曖昧でも動く」設計でした。
8.0以降は「正しく比較する」設計に近づいています。
その結果、トラブルは減りますが、
曖昧な前提で動いていたシステムは動かなくなります。
つまり8.0は新しい機能が増えたというより、
データの扱い方の前提が変わったバージョンと考えると理解しやすいです。