MySQL 默認字符集 `latin1` 是中文亂碼的元兇。本文提供標準化 `my.cnf` 配置模板,深度解析 `utf8` (utf8mb3) 與 `utf8mb4` 的區別、`general_ci`/`unicode_ci`/`bin` 校對規則差異,並給出生產環境字符集遷移清單。
[client] default-character-set = utf8mb4 [mysql] default-character-set = utf8mb4 [mysqld] # 關鍵:服務端字符集與校對 character-set-server = utf8mb4 collation-server = utf8mb4_general_ci # 關鍵:跳過客戶端字符集握手,強制使用服務端設置 skip-character-set-client-handshake # 可選:連接初始化命令 (5.7+ 推薦用 skip-character-set-client-handshake 替代) # init_connect = 'SET NAMES utf8mb4 COLLATE utf8mb4_general_ci'
⚠️ **嚴禁**在 `[mysqld]` 下使用 `default-character-set`,會導致啟動報錯 `unknown variable 'default-character-set'`。
| 特性 | utf8 (utf8mb3) | utf8mb4 |
|---|---|---|
| 最大字符長度 | 3 字節 | 4 字節 |
| Unicode 覆蓋 | BMP 平面 (U+0000 ~ U+FFFF) | 全部 Unicode (含輔助平面 U+10000 ~ U+10FFFF) |
| Emoji 支援 | ❌ 存儲為 ? 或亂碼 | ✅ 完美支援 |
| 生僻字支援 | ❌ 部分漢字無法存儲 | ✅ 完整支援 |
| 索引長度限制 | 767 字節 = 255 字符 | 767 字節 = 191 字符 (InnoDB 默認) |
| 存儲空間 | 基準 | +0~33% (僅非 BMP 字符佔 4 字節) |
| MySQL 版本 | ≤ 5.5 默認 | 5.5.3+ 支援,8.0 默認 |
結論:**無條件選 utf8mb4**。索引長度限制可通過 `innodb_large_prefix=ON` + `innodb_file_format=Barracuda` + `ROW_FORMAT=DYNAMIC/COMPRESSED` 解除 (3072 字節 = 768 字符),5.7.7+ 默認已開啟。
| 校對 | 比較規則 | 性能 | 典型差異 | 建議場景 |
|---|---|---|---|---|
| utf8mb4_general_ci | 簡化規則:ß=s, Œ=OE, 不分音標 | 快 | 德語 ß = s;法語 é = e | 🏆 **通用業務首選** (中文無影響、速度快) |
| utf8mb4_unicode_ci / 0900_ai_ci | 嚴格 Unicode 標準 (UCA) | 慢 | 德語 ß = ss;法語按音標排序 | 多語言嚴格排序、歐洲本地化應用 |
| utf8mb4_bin | 二進制字節比較 | 最快 | 大小寫敏感、'A' ≠ 'a' | 密碼、Token、精確匹配、大小寫敏感業務 |
💡 **國內業務建議**:`utf8mb4` + `utf8mb4_general_ci`。8.0 默認 `utf8mb4_0900_ai_ci` (Unicode 9.0、重音不敏感、大小寫不敏感),性能優於 `unicode_ci`,兼容性更好。