mysql 8.0默认用utf8mb4是因为旧utf8(即utf8mb3)仅支持3字节编码,无法存储emoji等4字节unicode字符,插入必报incorrect string value;其本质是历史别名,maxlen为3,不兼容辅助平面字符。

MySQL 8.0 默认用 utf8mb4,不是为了“升级体验”,而是因为旧的 utf8(实际是 utf8mb3)根本存不了 emoji 和大量现代 Unicode 字符——一插就报 Incorrect string value,这是硬性限制。
为什么 utf8 在 MySQL 里存不了 emoji?
MySQL 的 utf8 是个历史别名,最多只支持 3 字节编码,对应 Unicode 基本多文种平面(BMP)。而 emoji、U+20000 起的扩展汉字、部分数学符号等都落在辅助平面,必须用 4 字节编码才能表示。\xF0\x9F\x92\x95 这类字节序列在 utf8 下直接被截断或拒绝。执行 SHOW CHARSET LIKE 'utf8' 可见 Maxlen 是 3,不是 4。
utf8mb4 生效必须三层一致,光改 character-set-server 没用
MySQL 字符集行为由客户端、服务端、连接会话三者共同决定:
-
character_set_server只影响新库/新表默认值,不改变已有对象 -
character_set_client决定客户端传入字节如何解码 -
character_set_connection和character_set_results控制中间转换与返回结果编码
只在 [mysqld] 段设 character-set-server = utf8mb4,SHOW VARIABLES LIKE 'character%' 中仍可能看到 utf8 或 latin1 ——常见于配置写错段落(比如误写进 [mysqld_safe])、路径不对、或被其他同名项覆盖。
MySQL 8.0.28 起,utf8 已被官方标记为「已弃用」
这不是建议,是明确淘汰信号。即使你没主动用 utf8,某些旧工具、脚本或迁移流程仍可能隐式触发它。更关键的是:utf8mb4 不只是多支持几个字符,它绑定了更准确的排序规则 utf8mb4_0900_ai_ci(基于 Unicode 9.0),而 utf8mb4_general_ci 等老规则在大小写、重音、德语 ß 等场景下行为不准,容易导致查询漏匹配或误去重。
改完 utf8mb4,索引和建表容易静默失败
VARCHAR(255) 在 utf8mb4 下理论最大占 1020 字节,超过 InnoDB 默认单列索引上限(767 字节),会报 Specified key was too long。必须同时确保:
innodb_file_format = Barracudainnodb_file_per_table = ONinnodb_large_prefix = ON- 建表或转换时显式指定
ROW_FORMAT = DYNAMIC
漏掉任一条件,ALTER TABLE ... CONVERT TO CHARACTER SET utf8mb4 可能看似成功,但字段实际仍是 utf8 编码,或者索引被悄悄降级为前缀索引。
真正要盯住的不是“改成 utf8mb4”这个动作,而是字段定义是否显式声明 CHARACTER SET utf8mb4、连接层是否统一声明 charset=utf8mb4、以及索引键长度是否在物理层面撑得住——这三件事漏一个,问题就会在某个低概率 emoji 插入、某次跨表 JOIN 或某次 ORDER BY 时突然爆发。











