utf8mb4_0900_ai_ci是MySQL 8.0默认校对集,适用于用户昵称等语义等价容忍场景;但密码、token等需精确匹配字段应选_utf8mb4_bin或_utf8mb4_0900_as_cs,避免大小写/重音不敏感引发安全隐患。

utf8mb4_0900_ai_ci 是默认,但不是万能解
MySQL 8.0 默认用 utf8mb4_0900_ai_ci,它确实覆盖了绝大多数中文、英文、Emoji 和常见多语言场景。但它不等于“所有字段都该用它”。比如密码哈希值、JWT token、API key 这类需要精确字节匹配的字段,utf8mb4_0900_ai_ci 的大小写/重音不敏感特性反而会引入隐患:WHERE token = 'Abc123' 可能意外匹配到 'abc123'。
真正该优先考虑 utf8mb4_0900_ai_ci 的是用户昵称、商品标题、评论内容这类对“语义等价”有容忍度的字段。
区分大小写必须用 _cs 或 _bin,别信 _ci 后缀的“例外”
有人试过在 utf8mb4_0900_ai_ci 下加 BINARY 前缀或 COLLATE utf8mb4_bin 强制比较,结果发现 ORDER BY 或索引范围扫描变慢,甚至触发隐式转换警告。这不是 bug,是规则冲突:一个字段定义为 _ci,却在查询里强行用 _bin,MySQL 会在运行时做 collation 转换,代价不小。
- 要真需要大小写敏感(如邮箱登录校验),直接把字段定义成
COLLATE utf8mb4_0900_as_cs,别靠查询时补 -
utf8mb4_bin最快也最严格,适合 token、hash、base64 字符串,但注意它不按语言习惯排序——比如 'Z' 会排在 'a' 前面 - 别用
utf8mb4_general_ci:它基于 Unicode 4.0,对 ß=ss、ı=i 等处理错误,且 MySQL 8.0 已标记为废弃
跨语言排序别硬扛,用带语言后缀的规则
如果你的表要同时存中文、德文、越南文,又要求 ORDER BY name 返回符合各语言习惯的顺序(比如德语中 ä 排在 a 之后、z 之前),utf8mb4_0900_ai_ci 会按 Unicode 码点粗排,结果可能不符合本地用户直觉。
这时该查 MySQL 文档确认支持的语言列表,例如:
面向 CRM 系统的 MySQL 8 数据库模式设计。当用户需要为客户关系管理(CRM)系统设计、评审、优化或生成数据库模式时,应使用此项技能。
- 德语用户为主 →
utf8mb4_german2_ci(注意不是german_ci,那是旧版) - 越南语 →
utf8mb4_vietnamese_ci - 中文精确排序(如按拼音首字母分组)→
utf8mb4_zh_0900_as_cs,但需确认客户端连接也设对character_set_client
这些规则不能混用:一张表里既有 _zh_0900_as_cs 字段又有 _german2_ci 字段,JOIN 时照样报 ERROR 1267。
修改排序规则不等于数据自动重排,索引得手动重建
执行 ALTER TABLE t MODIFY c VARCHAR(100) COLLATE utf8mb4_0900_as_cs 后,数据本身没变,只是比较逻辑变了。但原有索引仍按旧规则组织,可能导致:
- WHERE c = 'A' 扫描全表(因索引 B+ 树结构未适配新 collation)
- ORDER BY c DESC 返回乱序(索引失效,走文件排序)
务必跟一句:ALTER TABLE t DROP INDEX idx_c, ADD INDEX idx_c(c);。大表操作前先 SET SESSION sort_buffer_size = 268435456;,避免临时文件撑爆磁盘。
最容易被忽略的是连接层:即使表、列、数据库全设成 utf8mb4_0900_ai_ci,如果应用连接时没发 SET NAMES utf8mb4; 或没在连接字符串里指定 charset=utf8mb4,MySQL 仍用 latin1 解析传入的字节,café 变成 café,再准的排序规则也救不回来。










