MySQL 8.0默认排序规则由character_set_server硬编码绑定,utf8mb4对应utf8mb4_0900_ai_ci;collation_server为只读变量,设了报错;老表不自动升级,新对象才生效,混用不同collation会触发Illegal mix错误。

utf8_general_ci 从来就不是 MySQL 8.0 的默认排序规则——它压根没在 utf8mb4 字符集下当过默认值。你看到的“变化”,其实是 utf8mb4_general_ci → utf8mb4_0900_ai_ci 的升级,不是从 utf8_general_ci 变过来的。
MySQL 8.0 默认排序规则到底绑定在哪?
它由 character_set_server 硬编码决定,不是靠配置项动态选的:
- 如果 character_set_server = utf8mb4(MySQL 8.0 默认就是这个),那新建库/表/字段的默认 collation 就是 utf8mb4_0900_ai_ci;
- collation_server 在 8.0+ 是只读变量,设了也报错:Variable 'collation_server' is a read only variable;
- 这个绑定关系在 mysqld 启动时就固化了,运行时无法覆盖。
为什么非得换成 utf8mb4_0900_ai_ci?
因为 utf8mb4_general_ci 是个“凑合用”的老算法,基于过时的 Unicode 4.0,实际行为不准:
- 把德语 ß 和 ss 当作相等,但搜索时可能漏匹配或误去重;
- 把带重音的 é 和 e 视为相同,导致 WHERE name = 'cafe' 意外命中 'café';
- 对 emoji、CJK 扩展区汉字、越南语声调等完全没定义排序逻辑;
- utf8mb4_0900_ai_ci 基于 Unicode 9.0 归类算法(UCA 9.0.0),真正按语言习惯处理比较和排序。
Illegal mix of collations 错误怎么来的?
这是最常踩的坑,本质是字段、表达式、JOIN 条件里混用了不同 collation:
- 查具体字段:执行 SHOW FULL COLUMNS FROM table_name,看 Collation 列是否不一致;
- 临时绕过:在查询里加 COLLATE utf8mb4_0900_ai_ci,比如 WHERE col1 = col2 COLLATE utf8mb4_0900_ai_ci;
- 长期修复:逐字段改,例如 ALTER TABLE t MODIFY name VARCHAR(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci;
- 注意:CONVERT TO CHARACTER SET utf8mb4 会自动套用当前默认 collation,大表要评估锁和耗时。
已有老表不会自动升级,这点最容易被忽略
哪怕你重启 mysqld、改了所有配置,SHOW CREATE TABLE old_table 依然显示 COLLATE=utf8mb4_general_ci。
- 新建对象才走新规则,老对象保持原样;
- 升级后第一次 JOIN 或 ORDER BY 跨字段/跨表操作,就可能直接报错;
- 不是“配置没生效”,是 MySQL 8.0 显式拒绝隐式转换——必须手动统一,没有捷径。


















