| 層級 | 系統變數 | 作用範圍 | 典型設定 |
| 伺服器 | character_set_server | 預設資料庫/表/欄位 | utf8mb4 |
| 資料庫 | character_set_database | 該資料庫新建表預設 | utf8mb4 |
| 資料表 | TABLE CHARSET | 該表新建欄位預設 | utf8mb4 |
| 欄位 | COLUMN CHARSET | 實際儲存編碼 | utf8mb4 |
| 連線 | character_set_client/connection/results | 客戶端↔伺服器傳輸編碼 | utf8mb4 |
| 結果集 | character_set_results | 伺服器→客戶端編碼 | utf8mb4 |
utf8 vs utf8mb4:核心差異
| 特性 | utf8 (utf8mb3) | utf8mb4 |
| 最大位元組/字元 | 3 bytes | 4 bytes |
| 支援 Unicode 範圍 | 基本多文種平面 (BMP, U+0000-U+FFFF) | 完整 Unicode (含輔助平面 Emoji、生僻字) |
| MySQL 版本 | 5.5.3 前預設 | 5.5.3+ 可用,8.0 預設 |
| 索引長度限制 | 767 bytes (InnoDB) | 767 bytes (需 innodb_large_prefix=ON 解除 3072 bytes) |
結論:全面棄用 utf8,統一使用 utf8mb4。MySQL 8.0 已將 utf8 別名指向 utf8mb3(即將移除)。
校對規則選擇指南
utf8mb4_unicode_ci:依 Unicode 標準排序(準確支援多語言)、效能略低 → 推薦預設
utf8mb4_general_ci:舊版簡化排序(較快但不準,如 ß=s、œ=oe) → 相容舊系統用
utf8mb4_0900_ai_ci:MySQL 8.0 新預設,支援 Unicode 9.0、語言無關、效能優化 → 8.0 首選
utf8mb4_bin:二進制比較,區分大小寫/重音,適合精確匹配(如密碼雜湊)
連線字符集「三件套」設定
客戶端連線時需三者一致,否則發生隱性轉碼導致亂碼:
SET NAMES utf8mb4 COLLATE utf8mb4_unicode_ci;
-- 等同於
SET character_set_client = utf8mb4;
SET character_set_connection = utf8mb4;
SET character_set_results = utf8mb4;
各語言/框架設定方式
| 環境 | 設定方式 |
| PHP PDO | $dsn = "mysql:host=...;charset=utf8mb4"; |
| PHP mysqli | $mysqli->set_charset("utf8mb4"); |
| Java JDBC | url?characterEncoding=utf8mb4&connectionCollation=utf8mb4_unicode_ci |
| Python PyMySQL | charset='utf8mb4' |
| Go sqlx | dsn "charset=utf8mb4,utf8" (驅動自動協商) |
| MySQL 客戶端 | mysql --default-character-set=utf8mb4 或 [client] default-character-set=utf8mb4 |
常見亂碼場景與根因
| 現象 | 根因 | 解決 |
| 中文變 ??? 或 亂碼 | 連線字符集非 utf8mb4(如 latin1),寫入時截斷/錯誤映射 | SET NAMES utf8mb4 / 修正連線配置 |
| Emoji 存成 ???? | 表/欄位字符集為 utf8 (3 bytes),無法儲存 4 bytes 字元 | ALTER TABLE ... CONVERT TO CHARSET utf8mb4 |
| 查詢結果正常,應用顯示亂碼 | 應用讀取時未指定 charset,預設 latin1/系統編碼解碼 | 應用層指定 utf8mb4 解碼 |
| ORDER BY 排序異常 | 校對規則不支援該語言(如 general_ci 對中文拼音排序無效) | 改用 unicode_ci 或指定語言校對 |
遷移現有資料庫至 utf8mb4 完整步驟
- 備份:
mysqldump --single-transaction --routines --triggers -u root -p db > backup.sql
- 修改配置:
my.cnf 設定 character_set_server=utf8mb4、collation_server=utf8mb4_unicode_ci
- 轉換資料庫:
ALTER DATABASE db CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci;
- 轉換每張表:
ALTER TABLE tbl CONVERT TO CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
- 檢查欄位長度:
VARCHAR(255) 在 utf8mb4 佔 1020 bytes,可能超過索引限制 → 改 VARCHAR(191) 或開啟 innodb_large_prefix=ON + innodb_file_format=Barracuda + ROW_FORMAT=DYNAMIC
- 驗證:插入 Emoji 測試、檢查
SHOW CREATE TABLE、應用端全鏈路測試
總結
MySQL 字符集核心原則:全鏈路 utf8mb4 + unicode_ci/0900_ai_ci。伺服器、資料庫、表、欄位、連線、應用層六個層級全部對齊,才能徹底杜絕亂碼。MySQL 8.0 已將此設為預設,舊版升級務必執行完整遷移流程。
- 上一篇文章: MySQL 刪除欄位為空 (NULL 或空字串) 的資料完整指南
- 下一篇文章: MySQL DATE_FORMAT 函數內建格式化符號完整參考表
Copyright ©
程式碼之家 All Rights Reserved