当前位置: 代码网 > it编程>数据库>Mysql > MySQL字符集与排序规则utf8mb4、utf8mb3、collation选型与避坑总结(可直接当团队规范)

MySQL字符集与排序规则utf8mb4、utf8mb3、collation选型与避坑总结(可直接当团队规范)

2026年01月25日 Mysql 我要评论
前言一句话定调:新项目永远选 utf8mb4 + utf8mb4_0900_ai_ci。绝大多数“中文乱码/emoji 报错/唯一索引异常/大小写不一致”的锅,最后都能追到:字

前言

一句话定调:新项目永远选 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 = utf8mb4
  • collation_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(推荐)
最大字节34
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_ci
    • 0900:unicode 9.0
    • ai: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,你以为 tomtom 是两个人,但数据库认为相等,唯一索引直接冲突。

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 下:tomtom 认为相等
  • 如果账号体系需要区分大小写(少见,但存在),要用 _bin 或特定 _cs

6. 快速参考(直接贴到文档里)

6.1 选型速查表

场景字符集排序规则备注
新项目(mysql 8)utf8mb4utf8mb4_0900_ai_ci⭐ 默认推荐
老项目兼容(mysql 5.7)utf8mb4utf8mb4_unicode_ci兼容优先
需要严格大小写敏感utf8mb4utf8mb4_bintoken/签名/账号等
❌ 不要用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内容请搜索代码网以前的文章或继续浏览下面的相关文章希望大家以后多多支持代码网!

(0)

相关文章:

版权声明:本文内容由互联网用户贡献,该文观点仅代表作者本人。本站仅提供信息存储服务,不拥有所有权,不承担相关法律责任。 如发现本站有涉嫌抄袭侵权/违法违规的内容, 请发送邮件至 2386932994@qq.com 举报,一经查实将立刻删除。

发表评论

验证码:
Copyright © 2017-2026  代码网 保留所有权利. 粤ICP备2024248653号
站长QQ:2386932994 | 联系邮箱:2386932994@qq.com