MySQL 字符集和排序规则有什么区别?utf8mb4 为什么更推荐?
简化版
字符集决定字符如何编码存储,排序规则决定字符如何比较和排序。MySQL 里的 utf8 历史上通常是 utf8mb3,最多 3 字节,不能完整存储 emoji 等 4 字节 Unicode 字符;utf8mb4 才是更完整的 UTF-8 实现。实际建库建表更推荐统一使用 utf8mb4,排序规则按是否区分大小写、重音和语言习惯选择。
详细版
字符集解决“能不能存、怎么存”,排序规则解决“怎么比、怎么排”。比如同样是 utf8mb4 字符集,不同 collation 下,A 和 a 是否相等、中文如何排序、是否区分重音,结果都可能不同。
面试中要特别提 MySQL 的 utf8 命名历史问题。很多老系统使用 utf8,实际是 utf8mb3,遇到 emoji、部分生僻字或特殊符号会报错或截断。新项目通常推荐 utf8mb4,并在库、表、列、连接层保持一致。
完整版教学
一、字符集是什么
字符集定义字符到字节的编码方式。
数据库需要知道一个字符串如何存进磁盘。
如果字符集不支持某个字符,插入时可能报错。
常见字符集包括 latin1、gbk、utf8mb3、utf8mb4。
现代中文和国际化项目一般选择 utf8mb4。
二、排序规则是什么
排序规则也叫 collation。
它定义字符串比较和排序规则。
同一字符集可以有多个排序规则。
例如是否大小写敏感、是否重音敏感、是否按二进制比较。
所以字符集和排序规则不是一回事。
三、utf8mb4 的意义
MySQL 的 utf8 曾长期表示 utf8mb3。
utf8mb3 最多使用 3 字节表示一个字符。
完整 Unicode 中有些字符需要 4 字节。
emoji 就是线上最常见的例子。
因此新系统更推荐直接使用 utf8mb4。
四、常见配置层级
| 层级 | 作用 | 注意点 |
|---|---|---|
| server | 默认字符集 | 影响新建对象默认值 |
| database | 库默认字符集 | 建表未指定时继承 |
| table | 表默认字符集 | 列未指定时继承 |
| column | 列字符集 | 最终存储以列为准 |
| connection | 连接字符集 | 影响客户端和服务端传输 |
如果层级不一致,排查乱码会很痛苦。
五、建表示例
CREATE TABLE user_profile (
id BIGINT PRIMARY KEY,
nickname VARCHAR(64) NOT NULL
) CHARACTER SET utf8mb4
COLLATE utf8mb4_0900_ai_ci;
具体 collation 要看 MySQL 版本和业务规则。
如果要求大小写敏感,可以考虑 _bin 或对应 case-sensitive 规则。
六、索引长度影响
字符集会影响字符串字段占用字节数。
utf8mb4 每个字符最多 4 字节。
老版本 MySQL 对索引长度限制更敏感。
所以老系统从 utf8 升级到 utf8mb4 时,要检查索引长度、字段长度和版本限制。
字符集升级不是只改建表语句,还要评估历史数据、索引长度、连接参数和回滚方案。
七、误区和追问
- 误区:MySQL 的 utf8 就是完整 UTF-8。 很多版本里
utf8实际是utf8mb3,不支持 4 字节字符。 - 误区:字符集决定排序结果。 排序结果主要由 collation 决定。
- 误区:只改库默认字符集就能修复所有表。 已存在表和列不会自动全部变更。
- 追问:为什么 emoji 插入失败? 常见原因是列、表或连接层仍使用
utf8mb3。 - 追问:大小写不敏感是哪里控制的? 通常由 collation 控制,例如
_ci表示 case-insensitive。 - 追问:乱码怎么排查? 查列字符集、连接字符集、客户端编码和历史写入编码是否一致。
八、面试收束
回答时先区分字符集和排序规则。
再解释 MySQL utf8 与 utf8mb4 的历史差异。
最后补充配置层级、索引长度和线上迁移风险。