前言
一句话定调:新项目永远选 utf8mb4 + utf8mb4_0900_ai_ci。
绝大多数“中文乱码/emoji 报错/唯一索引异常/大小写不一致”的锅,最后都能追到:字符集/排序规则没统一。
0. 先搞清两个概念:字符集 vs 排序规则
- 字符集(character set):决定“字符怎么编码存储”(能不能存 emoji、本质占多少字节)
- 排序规则(collation):决定“字符怎么比较/排序”(是否大小写敏感、是否忽略重音、中文排序规则)
举个最直观的:
utf8mb4决定你能不能存😊utf8mb4_0900_ai_ci决定'a'是否等于'a'、é和e是否算相等、排序是否更准确
1. default character set 是否必须写?
1.1 结论(按场景给)
| 场景 | 是否必须写 | 说明 |
|---|---|---|
| 本地学习 / 临时库(mysql 8.x 默认 utf8mb4) | 可不写 | 省事,跟 datagrip 一样用 server 默认 |
| 团队项目 / 需要可复现 sql | 建议写 | 固定环境,避免“换机器就炸” |
| 生产环境 / 多环境部署(含 5.7/云厂商) | 必须写 | 防止默认值漂移导致隐蔽数据问题 |
1.2 datagrip 为什么默认不写?
因为它遵循“不写 = 用服务器默认”。
mysql 8.x 常见默认:
character_set_server = utf8mb4collation_server = utf8mb4_0900_ai_ci
因此下面两句在“默认未被你改过”的前提下等价:
-- datagrip 默认:不写 create database app_db; -- 显式写:更可控 create database app_db default character set utf8mb4 collate utf8mb4_0900_ai_ci;
1.3 怎么确认你机器/线上到底默认是什么?
show variables like 'character_set_server'; show variables like 'collation_server'; show variables like 'character_set_%'; show variables like 'collation_%';
✅ 建议把“线上默认值截图/记录”写进运维文档,否则迟早有人踩坑。
2. utf8mb3 vs utf8mb4:别再被utf8这个名字骗了
2.1 核心结论
- ✅ utf8mb4 = 真正的 utf-8(完整 unicode,支持 emoji)
- ❌ utf8mb3(或 utf8)= mysql 历史遗留的 3 字节 utf-8,不完整
mysql 里
utf8实际上长期等价于utf8mb3(只支持最多 3 字节),这就是最大误导点。
2.2 对比表
| 特性 | utf8mb3(utf8) | utf8mb4(推荐) |
|---|---|---|
| 最大字节 | 3 | 4 |
| emoji | ❌ 不支持 | ✅ 支持 |
| unicode 完整性 | ❌ 不完整 | ✅ 完整 |
| mysql 8.x 状态 | deprecated(废弃趋势) | ✅ 默认推荐 |
2.3 最典型的报错
-- 在 utf8mb3/utf8 表里插入 emoji 往往会失败
insert into user(username) values ('张三😊');
常见错误类似:
incorrect string value: '\xf0\x9f...' for column ...
2.4 为什么“新项目用 utf8mb3 = 技术债”?
因为这不是“是否需要 emoji”的问题:
- 你永远无法保证用户输入、第三方接口、运营文案、复制粘贴内容不出现 4 字节字符
- 一旦出现,轻则插入失败,重则数据截断、业务异常、日志污染
3. 排序规则(collation)怎么选:0900_ai_ci vs unicode_ci vs bin
排序规则名字拆开看:
utf8mb4_0900_ai_ci0900:unicode 9.0ai:accent-insensitive(忽略重音)ci:case-insensitive(不区分大小写)
3.1 常见三种排序规则的定位
a)utf8mb4_0900_ai_ci(mysql 8.x 推荐默认)
✅ 适合:绝大多数业务表、用户输入、通用字符串
特点:
- unicode 9.0,规则更新更全
- 比旧版 unicode_ci 更准确
- 性能通常更好(实现更现代)
b)utf8mb4_unicode_ci(兼容旧项目/5.7 常用)
✅ 适合:历史系统已用该排序规则,或需兼容 mysql 5.7
特点:
- 规则更旧(非 9.0)
- 通常也够用,但不是最优
c)utf8mb4_bin(严格区分大小写/二进制比较)
✅ 适合:密码 hash、token、大小写敏感账号、签名、验证码、唯一标识
特点:
a ≠ a- 比较按字节序(“最严格”)
3.2 重点后缀:_ci / _cs / _bin
| 后缀 | 含义 | 示例 |
|---|---|---|
_ci | 不区分大小写 | tom = tom |
_cs | 区分大小写(某些 collation 有) | tom ≠ tom |
_bin | 二进制比较,严格区分 | tom ≠ tom |
⚠️ 业务最容易踩的坑:用户名/邮箱用
_ci,你以为tom和tom是两个人,但数据库认为相等,唯一索引直接冲突。
4. 实战建议:怎么给“库/表/字段”落地标准?
4.1 新项目(mysql 8.x)标准建库模板(推荐)
create database app_db default character set utf8mb4 collate utf8mb4_0900_ai_ci;
4.2 兼容 mysql 5.7(或老项目迁移)模板
create database app_db default character set utf8mb4 collate utf8mb4_unicode_ci;
4.3 建表时建议也显式写(团队协作更稳)
create table user ( id bigint primary key auto_increment, username varchar(50) not null ) engine=innodb default charset=utf8mb4 collate=utf8mb4_0900_ai_ci;
4.4 字段级别什么时候需要单独设置?
一般不需要,继承库/表的默认即可。
只有在“局部需要强规则”时才做字段级设置:
-- token/密钥/大小写敏感字段 token varchar(64) character set utf8mb4 collate utf8mb4_bin not null;
5. 常见坑位提醒(面试/线上事故高频)
5.1 唯一索引长度问题(老版本)
- utf8mb4 下
varchar(255)最坏是255 * 4 = 1020 bytes - mysql 5.6/早期 5.7 可能受限(767 bytes 等历史限制)
- mysql 8 大多无需担心,但老环境可能要:
- 改
varchar(191) - 或用前缀索引
- 改
5.2 “同一库里表的 collation 不一致”导致的隐蔽 bug
表现:
- join/union 报错:
illegal mix of collations - 比较结果异常、排序不一致
解决: - 统一库 → 表 → 字段层级的默认值
- 迁移时用脚本批量检查并修正
5.3 大小写不敏感导致唯一索引误伤
utf8mb4_0900_ai_ci下:tom和tom认为相等- 如果账号体系需要区分大小写(少见,但存在),要用
_bin或特定_cs
6. 快速参考(直接贴到文档里)
6.1 选型速查表
| 场景 | 字符集 | 排序规则 | 备注 |
|---|---|---|---|
| 新项目(mysql 8) | utf8mb4 | utf8mb4_0900_ai_ci | ⭐ 默认推荐 |
| 老项目兼容(mysql 5.7) | utf8mb4 | utf8mb4_unicode_ci | 兼容优先 |
| 需要严格大小写敏感 | utf8mb4 | utf8mb4_bin | token/签名/账号等 |
| ❌ 不要用 | utf8 / utf8mb3 | - | 历史遗留 |
6.2 常用排查命令
-- 服务器默认 show variables like 'character_set_server'; show variables like 'collation_server'; -- 数据库定义 show create database app_db; -- 表定义 show create table user; -- 当前连接字符集(很重要,决定客户端发给服务端怎么编码) show variables like 'character_set_client'; show variables like 'character_set_connection'; show variables like 'character_set_results';
7. 记忆口诀(文章收尾加分)
- utf8mb4 是唯一正确选择
- utf8/utf8mb3 是历史遗留
- mysql 8 默认:utf8mb4_0900_ai_ci
- 要区分大小写:用 utf8mb4_bin
最后一段总结(可直接当结尾)
跨环境最怕的不是“你写错”,而是“你没写”,让默认值悄悄决定了线上行为。
所以:本地可以省略,项目/生产必须显式指定。
只要把 utf8mb4 + 合理 collation 统一了,乱码、emoji 报错、比较排序异常、mix collations 等问题会少一大半。
到此这篇关于mysql字符集与排序规则utf8mb4、utf8mb3、collation选型与避坑总结的文章就介绍到这了,更多相关mysql utf8mb4、utf8mb3、collation内容请搜索代码网以前的文章或继续浏览下面的相关文章希望大家以后多多支持代码网!
发表评论