mysql 8.0默认排序规则变更为utf8mb4_0900_ai_ci是源码硬编码行为,非配置错误;character_set_server=utf8mb4时自动绑定该collation,collation_server变量在8.0+中只读且仅影响连接初始化,不参与对象创建。

MySQL 8.0 默认排序规则变更是硬编码行为,不是配置错误
MySQL 8.0 把新建库/表的默认 collation 从 utf8mb4_general_ci 改成 utf8mb4_0900_ai_ci(或 utf8mb4_0900_as_cs),不是 bug,也不是配置漏了——这是源码里写死的映射逻辑:只要 character_set_server = utf8mb4,就自动绑定 utf8mb4_0900_ai_ci,完全不读 collation-server 的值。
你执行 SET GLOBAL collation_server = 'utf8mb4_general_ci' 会直接报错:Variable 'collation_server' is a read only variable。这不是权限问题,是 MySQL 8.0+ 明确禁写了这个变量。
-
collation-server在 8.0+ 中只影响新连接初始化时的collation_connection,不参与建库、建表逻辑 - 真正起作用的是
character_set_server的值,它决定了“该字符集下哪个 collation 是默认的” - 这个绑定关系在服务器启动时就固化了,无法运行时覆盖
为什么选 utf8mb4_0900_ai_ci 而不是旧规则?
因为 utf8mb4_general_ci 是 MySQL 5.7 时代基于过时 Unicode 标准(约 4.0)的简化实现,存在大量不准确比较:
- 把
é和e当作相同字符(重音不区分) - 把德语
ß和ss视为等价(导致搜索/去重异常) - 对 emoji、数学符号、生僻汉字的排序无定义或随机
utf8mb4_0900_ai_ci 基于 Unicode 9.0 标准,支持更细粒度的语言规则(如法语重音敏感、土耳其语 I/i 特殊处理),_ai 表示 accent-insensitive,_ci 表示 case-insensitive——它不是“更松”,而是“更准”。
ORDER BY 结果变了,是不是要立刻回退?
不一定。先确认是不是真的业务逻辑受损,而不是“习惯了错误结果”:
- 执行
SELECT name FROM users ORDER BY name LIMIT 10;,再加COLLATE utf8mb4_general_ci对比,看差异是否影响功能 - 检查
=比较、GROUP BY、索引字段是否因大小写/重音敏感触发意外分组或失效 - 注意
utf8mb4_0900_as_cs(case-sensitive)和utf8mb4_0900_ai_ci(case-insensitive)是两个不同 collation,别混用
强行全局降级到 utf8mb4_general_ci 会削弱数据一致性,且 MySQL 后续版本可能彻底移除该规则支持。
最常被忽略的坑:已有对象不会自动更新
哪怕你改了配置、重启了 mysqld,SHOW CREATE DATABASE db1 还是显示 COLLATE=utf8mb4_0900_ai_ci,而老表里的字段 collation 仍是 utf8mb4_general_ci——这才是 Illegal mix of collations 错误的根源。
必须手动逐层收敛:
- 数据库级:
ALTER DATABASE db1 CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci - 表级:
ALTER TABLE t1 CONVERT TO CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci - 字段级(若显式指定过旧 collation):
ALTER TABLE t1 MODIFY col VARCHAR(100) COLLATE utf8mb4_0900_ai_ci
没改完之前,任何跨字段比较、JOIN、UNION 都可能突然报错,而且错误位置往往不在你写的 SQL 里,而在底层隐式转换环节。











