优先选utf8mb4_0900_ai_ci;绝大多数web场景无需大小写敏感,它不区分大小写和重音符号,支持多语言排序,而utf8mb4_bin严格二进制比较,仅适用于密码、密钥等极少数必须区分大小写的字段。

用 utf8mb4_bin 还是 utf8mb4_0900_ai_ci?先看业务是否真需要大小写敏感
绝大多数 Web 应用的用户名、邮箱、商品名称等字段,**不需要**严格区分大小写。比如用户注册 alice@example.com 和 Alice@example.com 视为同一账号,这是合理且安全的。只有密码校验、验证码比对、API密钥存储等极少数场景,才必须保证 'Abc123' ≠ 'abc123'。盲目全表改 _bin 会破坏已有逻辑,比如唯一索引突然允许插入两条“仅大小写不同”的记录,或前端搜索结果变少。
WHERE name = 'X' 查询失效?小心 BINARY 修饰符让索引白建
临时加 BINARY 是最危险的“快捷解法”:
-
SELECT * FROM user WHERE BINARY password = 'Abc123'—— 即使password字段有索引,这条语句也大概率走全表扫描 -
ALTER TABLE user MODIFY password VARCHAR(32) BINARY—— 这个语法在 MySQL 8.0+ 已被弃用,实际执行会静默转为COLLATE utf8mb4_bin - 真正安全的做法是建表/改列时直接指定
COLLATE utf8mb4_bin,这样索引仍可正常使用
utf8mb4_bin 和 utf8mb4_0900_ai_ci 的真实差异不止大小写
两者不只是“敏感 vs 不敏感”,底层行为完全不同:
-
utf8mb4_bin:按 UTF-8 字节逐位比较,'ß'≠'ss','é'≠'e',连重音符号、德语变音都严格区分 -
utf8mb4_0900_ai_ci(MySQL 8.0 默认):“ai”=accent insensitive,“ci”=case insensitive,'É'、'é'、'e'都视为等价,排序也按语言习惯(如中文拼音、德语词序) - 如果业务涉及多语言用户,用
_bin可能导致搜索“Li”搜不出“李”,而_0900_ai_ci能更好支持国际化
修改已有字段的 collation 时,ALTER TABLE ... MODIFY 比 CONVERT TO 更可控
想把某列从 _ci 改成 _bin,别用 CONVERT TO CHARACTER SET utf8mb4 COLLATE utf8mb4_bin —— 它会强制重写整张表,锁表时间长,且可能意外改变其他列的 collation。
更稳妥的方式是明确指定目标列:
ALTER TABLE user_auth MODIFY password VARCHAR(32) COLLATE utf8mb4_bin NOT NULL;
注意三点:
- 必须完整重复原字段定义(类型、长度、约束),否则可能丢失
NOT NULL或默认值 - 该操作在 MySQL 5.7+ 是 online DDL(不锁表),但仍有短暂元数据锁
- 改完后务必验证:执行
SHOW CREATE TABLE user_auth确认 collation 已生效,再用SELECT 'A' = 'a' COLLATE utf8mb4_bin测试返回是否为0
真正容易被忽略的是 collation 的继承链:数据库级、表级、列级 collation 会逐层覆盖,只改列却不检查上层设置,可能被悄悄覆盖掉。











