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

 更新时间:2026年01月24日 09:13:15   作者:IT枫斗者  
MySQL提供了多种字符集和排序规则选择,其中字符集设置和数据存储以及客户端与MySQL实例的交互相关,这篇文章主要介绍了MySQL字符集与排序规则utf8mb4、utf8mb3、collation选型与避坑总结的相关资料,需要的朋友可以参考下

前言

一句话定调:新项目永远选 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内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

您可能感兴趣的文章:

相关文章

  • mysql之set与enum的介绍

    mysql之set与enum的介绍

    本篇文章是对mysql中的set与enum进行了详细的分析介绍,需要的朋友参考下
    2013-06-06
  • 安装配置Zabbix来监控MySQL的基本教程

    安装配置Zabbix来监控MySQL的基本教程

    这篇文章主要介绍了安装配置Zabbix来监控MySQL的基本教程,Zabbix拥有web页面端显示数据的功能,文中的安装环境为CentOS系统,需要的朋友可以参考下
    2015-12-12
  • mysql between实现选取介于两个值之间的数据范围

    mysql between实现选取介于两个值之间的数据范围

    这篇文章主要介绍了mysql between实现选取介于两个值之间的数据范围,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
    2022-07-07
  • mysql 的load data infile

    mysql 的load data infile

    前些日子在开发一个舆情监测系统,需要在一个操作过程中往数据表里插入大量的数据,为了改变以往生硬地逐条数据插入的笨办法,也为了提高执行效率,决定用load data infile来执行数据插入。
    2009-05-05
  • 在MySQL中使用子查询和标量子查询的基本操作教程

    在MySQL中使用子查询和标量子查询的基本操作教程

    这篇文章主要介绍了在MySQL中使用子查询和标量子查询的基本操作教程,子查询的使用时MySQL入门学习中的基础知识,需要的朋友可以参考下
    2015-12-12
  • MySQL对JSON类型字段数据进行提取和查询的实现

    MySQL对JSON类型字段数据进行提取和查询的实现

    本文主要介绍了MySQL对JSON类型字段数据进行提取和查询的实现,文中通过示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2022-04-04
  • MySQL中的聚集索引、二级索引使用解读

    MySQL中的聚集索引、二级索引使用解读

    这篇文章主要介绍了MySQL中的聚集索引、二级索引使用,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教
    2025-07-07
  • mysql导出导入中文表解决方法

    mysql导出导入中文表解决方法

    在开发过程中会经常用到mysql导出导入中文表,本文将详细介绍其如何使用,需要的朋友可以参考下
    2012-11-11
  • mysql 8.0.12 安装使用教程

    mysql 8.0.12 安装使用教程

    这篇文章主要为大家详细介绍了mysql 8.0.12 安装使用教程,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2018-08-08
  • mysql如何比对两个数据库表结构的方法

    mysql如何比对两个数据库表结构的方法

    这篇文章主要介绍了mysql如何比对两个数据库表结构的方法,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2019-09-09

最新评论