MySQL 早期 utf8 僅支援 BMP(基本多文種平面,3 字節),無法存儲 Emoji(SMP,4 字節)及擴展漢字(SIP)。本文從 Unicode 平面劃分、UTF-8 編碼原理、utf8mb4 兼容性、索引長度限制、性能影響、遷移實戰六大維度全景解析,助你徹底解決「Incorrect string value」報錯。
utf8 覆蓋| 特性 | utf8 (utf8mb3) | utf8mb4 |
|---|---|---|
| 最大字節數 | 3 | 4 |
| 覆蓋 Plane | 僅 BMP | 全部 17 個 Plane |
| Emoji 支援 | ❌ 報錯 | ✅ 正常 |
| 生僻漢字 | ❌ 報錯 | ✅ 正常 |
| BMP 字符存儲 | 相同 | 相同,無額外開銷 |
| VARCHAR 最大字符數 | 21844 (65535/3) | 16383 (65535/4) |
| InnoDB 索引長度限制 | 767 字節 → 255 字符 | 767 字節 → 191 字符 |
| 性能 | 基準 | 索引稍大,極高並發下微弱劣勢 |
ALTER DATABASE db_name CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci;ALTER TABLE tbl_name CONVERT TO CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;ALTER TABLE tbl_name MODIFY col VARCHAR(191) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;SET NAMES utf8mb4 或 JDBC URL 加 characterEncoding=utf8mb4ALTER TABLE t DROP INDEX idx, ADD INDEX idx(col(191));-- 測試 Emoji
INSERT INTO t(c) VALUES ('😀🎉🚀');
SELECT c, HEX(c), CHAR_LENGTH(c) FROM t;
-- 測試生僻字(擴展 B 區)
INSERT INTO t(c) VALUES ('𠮷𠮷'); -- U+20BB7
SELECT c, HEX(c) FROM t;
utf8mb4_unicode_ci:基於 UCA(Unicode Collation Algorithm),準確支援多語言排序,推薦通用場景。utf8mb4_general_ci:簡化規則,速度略快但德語 ß、法語 à 等排序不準,僅舊系統相容用。utf8mb4_0900_ai_ci(MySQL 8.0+):最新 UCA 9.0,支援表情符號排序、無重音不敏感,首選新項目。若系統頻繁寫入標題、評論等用戶生成內容,強烈建議直接遷移至 utf8mb4。性能損耗可忽略,數據完整性與用戶體驗收益遠大於成本。若絕對禁止遷移,應用層必須過濾/轉義 4 字節字符,但會導致數據失真。