mysql 8.0 默认用 utf8mb4 是因旧 utf8(即 utf8mb3)仅支持 3 字节 unicode,无法存储 emoji、u+10000 起生僻汉字等 4 字节字符,插入必报 incorrect string value;必须同步配置服务端、数据库、表、字段、连接层及客户端工具的 utf8mb4 字符集与排序规则,并启用 innodb_large_prefix 和 row_format=dynamic。

MySQL 8.0 默认用 utf8mb4,不是为了“升级”或“兼容性更好”,而是因为旧的 utf8(实际是 utf8mb3)和 latin1 根本存不了 emoji、U+10000 起的生僻汉字、带多重变音符号的越南语字符——一插就报 Incorrect string value,这是硬性限制,不是配置没调好。
为什么 MySQL 的 utf8 存不了 emoji?
MySQL 的 utf8 是个历史别名,只支持最多 3 字节编码,对应 Unicode 基本多文种平面(BMP)。而 \xF0\x9F\x92\x95 这类 emoji、中文扩展 C 区汉字(如 U+20000)、某些数学符号都落在辅助平面,必须用 4 字节表示。SHOW CHARSET LIKE 'utf8' 显示的 Maxlen 是 3,不是 4;SHOW VARIABLES LIKE 'character_set_server' 返回 utf8 时,你看到的已经是 utf8mb3。
改了 my.cnf 就万事大吉?
只在 [mysqld] 段写 character-set-server = utf8mb4 远远不够。必须同时配齐三处:
-
[mysqld]:加collation-server = utf8mb4_0900_ai_ci和init_connect='SET NAMES utf8mb4' -
[client]:加default-character-set = utf8mb4(影响mysqldump、mysql命令行等所有客户端工具) -
[mysql]:加default-character-set = utf8mb4(专用于mysql命令行自身,不加可能被忽略)
Windows 用户注意路径:C:\phpEnv\MySQL\my.ini 或 C:\ProgramData\MySQL\MySQL Server X.X\my.ini;Docker 必须挂载自定义 my.cnf 到容器内 /etc/mysql/my.cnf,且权限设为 644,否则静默跳过。
ALTER TABLE CONVERT TO CHARACTER SET utf8mb4 容易踩哪些坑?
这条命令看着简单,但执行时极易静默失败或行为异常:
- 不会保留原字段的
COLLATION,而是套用当前默认排序规则(比如utf8mb4_0900_ai_ci),大小写敏感行为可能突变 - 若表未启用
ROW_FORMAT = DYNAMIC或innodb_large_prefix = ON,VARCHAR(255)加索引会因超 767 字节报Specified key was too long - 对已含
latin1编码数据的字段直接执行CONVERT TO,不等于“解码再重编码”,原始字节被错误解释,结果是乱码而非正确转换 - 连接层未设
charset=utf8mb4(如 JDBC URL 漏了&characterEncoding=utf8mb4),服务端配得再对也白搭,仍报Incorrect string value
真正要盯住的不是“改成 utf8mb4”这个动作,而是字段定义是否显式声明了 CHARACTER SET utf8mb4、索引键长度是否仍在 InnoDB 限制内、以及每一条连接是否真实按 utf8mb4 解析传入字节——漏掉任一环,emoji 就进不去,或者进去也是错的。











