mysql多语言支持靠字符集+校对规则双控;需在连接、库、表、列四层级统一配置utf8mb4与utf8mb4_unicode_ci,缺一不可,否则导致乱码或排序错误。

MySQL 多语言支持靠什么?不是装个插件,是字符集 + 校对规则双控
MySQL 本身不“懂”多语言,它只认 utf8mb4 这类编码和 utf8mb4_unicode_ci 这类校对规则。只要这两项在连接、库、表、列四个层级都对齐,中文、日文、emoji、阿拉伯文就能存得稳、查得准。错一个层级,就可能存乱码、排序错、大小写不敏感失效。
建库时没指定 CHARACTER SET 和 COLLATE,后面基本没法救
默认的 latin1 或旧版 utf8(实际只支持 BMP 字符)会导致 emoji 存成问号、越南文重音丢失、中文检索区分不了「张」和「張」。建库必须显式声明:
CREATE DATABASE myapp DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
-
utf8mb4是唯一能完整覆盖 Unicode 的 MySQL 字符集(utf8是阉割版) -
utf8mb4_unicode_ci比utf8mb4_general_ci更准,支持更细粒度的语言排序规则(比如德语 ß → ss) - 如果应用要支持土耳其语,得换
utf8mb4_tr_0900_as_cs这类带语言标识的校对规则
客户端连接不设 charset=utf8mb4,前面全白配
即使库和表全是 utf8mb4,只要连接层用的是 latin1,MySQL 就会把客户端发来的字节按 latin1 解码——中文立刻变乱码,且这个过程不可逆。
- PHP PDO:加
charset=utf8mb4到 DSN 里,如mysql:host=localhost;dbname=myapp;charset=utf8mb4 - Python PyMySQL:初始化时传
charset='utf8mb4' - 命令行
mysql -u root -p --default-character-set=utf8mb4 - 检查当前连接:执行
SHOW VARIABLES LIKE 'character_set%';,重点看character_set_client、character_set_connection、character_set_results全是utf8mb4
已有数据乱码了,不能直接 ALTER TABLE ... CONVERT TO
这是最常踩的坑:看到表是 latin1,想当然执行 ALTER TABLE t CONVERT TO CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci,结果中文全变问号或方块。因为 CONVERT 假设原数据是按当前列字符集正确编码的,而乱码数据实际是“错误解码后又错误存储”的字节流。
- 先确认原始字节:用
SELECT HEX(col) FROM t LIMIT 1;看是不是以C3A4、E5BCA0这类 UTF-8 编码开头 - 若确认源数据本是 UTF-8 字节但被当 latin1 存了,需用
CONVERT(CAST(CONVERT(col USING latin1) AS BINARY) USING utf8mb4)逐列修复 - 没有备份别硬改;线上环境优先导出再重建库
字符集不是开关,是贯穿连接、存储、传输的链路。漏掉任一环,多语言就卡在某个环节上不动。











