utf8mb4是MySQL中唯一完整支持Emoji和现代Unicode字符的字符集,其“mb4”表示最大支持4字节编码,而旧utf8实为utf8mb3,仅支持3字节,无法存储?等4字节字符。

utf8mb4 是唯一能完整支持 emoji 和现代 Unicode 字符的 MySQL 字符集,5.7 升级到 8.0 后必须用它,而不是“继续用 utf8”或“降级回 utf8”。
utf8 在 MySQL 里根本不是标准 UTF-8
MySQL 的 utf8 是历史遗留的 utf8mb3,最多只支持 3 字节编码。像 ?(U+1F60A)、??、生僻汉字 ? 这类 4 字节字符,插入时直接报错:Incorrect string value: '\xF0\x9F\x98\x8A'。
这不是配置没设对,是底层不支持。
-
utf8mb4才是真正的 UTF-8 实现(mb4= “max 4 bytes”) - MySQL 官方文档已将旧
utf8显式重命名为utf8mb3,并标记为不推荐用于新项目
升级后默认用 utf8mb4,但老表不会自动变
MySQL 8.0 启动时 character_set_server 默认是 utf8mb4,新建库/表也自动用 utf8mb4。
但 5.7 时期建的表,即使你当年写了 CHARACTER SET utf8mb4,它的排序规则(collation)大概率还是 utf8mb4_general_ci;而 8.0 新建表默认用的是 utf8mb4_0900_ai_ci。
这就埋下隐患:
- 跨表 JOIN 或
FIND_IN_SET()等操作会触发Illegal mix of collations错误 -
ORDER BY结果可能突变(比如中文排序从按二进制变成按拼音感知) - 唯一索引可能失效(
utf8mb4_general_ci对某些字判定为等价,utf8mb4_0900_ai_ci则更严格)
改字符集必须连带指定 collation,不能只写 CONVERT TO CHARACTER SET utf8mb4
这条语句看着完整,实则危险:ALTER TABLE t CONVERT TO CHARACTER SET utf8mb4;
它会把字段字符集改成 utf8mb4,但 collation 会悄悄套用当前 MySQL 版本的默认值——8.0 下就是 utf8mb4_0900_ai_ci。
如果其他表或列仍是 utf8mb4_general_ci,立刻引发混合 collation 报错。
正确做法是显式锁定 collation:
- 兼容性优先(尤其要兼顾 5.7 或旧应用):用
utf8mb4_general_ci或utf8mb4_unicode_ci - 准确性优先(纯 8.0 环境):用
utf8mb4_0900_ai_ci,但需确认所有关联字段、连接参数、应用层SET NAMES一致 - 别用
utf8_general_ci:它绑定的是utf8mb3,和utf8mb4不是一套体系
导出给低版本用时,--compatible=mysql57 不够,必须手动清理 collation
用 mysqldump 从 8.0 导出给 5.7 恢复,光加 --compatible=mysql57 不能解决 utf8mb4_0900_ai_ci 报错。
因为该参数只处理语法兼容(如窗口函数),不替换 collation。
必须:
- 先用
grep -n "utf8mb4_0900_ai_ci" dump.sql定位所有位置 - 替换三处:CREATE DATABASE 语句里的默认 collation、每个 CREATE TABLE 末尾的
COLLATE=...、每列定义后的COLLATE子句 - 同时确保导出时加了
--default-character-set=utf8mb4 --collation-server=utf8mb4_general_ci,否则连接层也可能带入 8.0 默认值
真正容易被忽略的点是:collation 不只是“建表时选一下”,它渗透在连接参数、字段定义、索引行为、甚至函数比较逻辑里。一次不一致,就可能让 WHERE name = 'abc' 突然匹配到 'ABC',或者让分页查询结果错乱。升级不是改完字符集就结束,而是要把整个 collation 链路拉通校验。











