mysql 8.0 中的 utf8 就是 utf8mb3,不支持 emoji、部分生僻汉字和 unicode 扩展区字符;它仅覆盖 bmp 平面(u+0000–u+ffff),无法存储 4 字节字符,插入必报 incorrect string value 错误。

MySQL 8.0 中的 utf8 就是 utf8mb3,它不支持 emoji、部分生僻汉字和 Unicode 扩展区字符——不是“不推荐”,而是根本存不了。
为什么 utf8 在 MySQL 8.0 里依然等于 utf8mb3
MySQL 官方至今没把 utf8 这个别名重定向到 utf8mb4。哪怕你写 CHARACTER SET utf8,MySQL 8.0(包括最新 8.0.34)仍会解析为 utf8mb3:
CREATE TABLE t (s VARCHAR(10)) CHARACTER SET utf8; SHOW CREATE TABLE t;
输出里明确显示 CHARACTER SET utf8mb3。这不是 bug,是兼容性保留——但对新项目毫无意义。
-
utf8mb3最大只支持 3 字节编码,覆盖 BMP 平面(U+0000–U+FFFF),漏掉所有四字节字符 - emoji 如
?、?、中文扩展 B 区汉字(如 U+20000 起)、越南语带多重音符字符,全都会触发Incorrect string value错误 - 连接层设置(如
init_connect='SET NAMES utf8')会被静默映射为utf8mb4,但**不改变字段定义本身**——字段仍是utf8mb3,照样存失败
utf8mb4 不只是“支持 emoji”,它才是真正的 UTF-8 实现
MySQL 的 utf8mb4 是唯一严格遵循 RFC 3629 的字符集,能完整表示 1–4 字节的 UTF-8 编码:
- 存储层面:
VARCHAR(255)在utf8mb4下最多占 1020 字节(255×4),而utf8mb3最多 765 字节(255×3)——索引长度限制(如 InnoDB 前缀索引最大 767/3072 字节)必须重新评估 - 排序规则必须匹配:用
utf8mb4就别混用utf8mb4_general_ci(已弃用);MySQL 8.0 默认是utf8mb4_0900_ai_ci,它基于 Unicode 9.0 归类算法,正确处理ß=ss、ä=a等语言逻辑 - 如果表里已有
utf8字段,ALTER TABLE ... CONVERT TO CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci会重建所有字符列——大表要预估锁时间和磁盘空间
怎么验证你的环境真能存 emoji,而不是“看起来可以”
别只查 SHOW VARIABLES LIKE 'character_set%' 或 SHOW VARIABLES LIKE 'collation%'——这些只反映连接/服务端配置,跟字段无关。
- 执行实测 SQL:
INSERT INTO t (s) VALUES (0xF09F988A);(这是 ? 的 UTF-8 四字节序列),看是否报错 - 用
SHOW CREATE TABLE t;确认每个字段的CHARACTER SET和COLLATE明确写着utf8mb4和utf8mb4_0900_ai_ci(或至少是utf8mb4_unicode_ci) - ORM 框架(如 Django、Rails、MyBatis)可能默认发
SET NAMES utf8,需显式配置为utf8mb4,否则连接层和字段层编码不一致,照样乱码
真正麻烦的不是改字符集,而是字段定义、索引限制、ORM 配置、历史数据校验这四层必须全部对齐——漏掉任何一层,emoji 都会在某个环节被截断或报错。











