mysql 8.0+ 中无法通过 set global collation_server 动态修改默认排序规则,它已是只读变量;必须在 [mysqld] 段同时配置 character-set-server = utf8mb4 和 collation-server = utf8mb4_unicode_ci 并重启服务才生效,且新库默认 collation 仍由字符集硬编码绑定(如 utf8mb4 → utf8mb4_0900_ai_ci),不直接采用 collation-server 值。

直接说结论:MySQL 8.0+ 中无法通过 SET GLOBAL collation_server 动态修改默认排序规则,它已是只读变量;真正生效的配置必须写在 [mysqld] 段下、配合 character-set-server = utf8mb4、重启服务才起作用。
为什么 SET GLOBAL collation_server 一定失败?
这不是权限问题,是 MySQL 8.0+ 的硬性设计:collation_server 被明确标记为只读系统变量。哪怕你有 SUPER 权限,执行也会报错:
ERROR 1238 (HY000): Variable 'collation_server' is a read only variable
常见误操作包括:
- 在 MySQL 客户端里反复试
SET GLOBAL,以为是账号权限不够 - 改完
my.cnf没重启mysqld,就去查SHOW VARIABLES LIKE 'collation_server',结果还是旧值 - 把配置写在
[client]或[mysql]段下——它只在[mysqld]段有效
my.cnf 里怎么配才真正生效?
必须同时设置两个参数,且顺序和位置不能错:
[mysqld] character-set-server = utf8mb4 collation-server = utf8mb4_unicode_ci
注意点:
- 不要加引号,值写成
utf8mb4_unicode_ci,不是'utf8mb4_unicode_ci' -
character-set-server必须先于collation-server,否则 MySQL 可能忽略后者 - 改完后必须重启服务:
sudo systemctl restart mysqld(Linux)或对应平台命令 - 验证是否加载成功:
mysqld --verbose --help | grep "Default collation",输出应含你设的值
改了 collation-server,新库就真用它吗?
不一定。MySQL 决定新数据库默认排序规则的逻辑是:先看 character-set-server 值,再查该字符集下“硬编码绑定”的默认 collation,而不是直接取 collation-server 的值。
例如:
- 设
character-set-server = utf8mb4→ MySQL 8.0+ 默认选utf8mb4_0900_ai_ci(不可更改) - 即使你写了
collation-server = utf8mb4_unicode_ci,新建库仍可能用utf8mb4_0900_ai_ci - 想让新库用
utf8mb4_unicode_ci,必须显式创建:CREATE DATABASE db_name CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci
已有数据排序乱,只改库级 COLLATE 没用
ALTER DATABASE ... COLLATE 只影响后续新建的表,对已有表、字段、索引完全无感。中文 ORDER BY 还是乱,大概率是因为字段本身定义的 collation 没变。
真正要改的是字段级 collation,优先级最高:
- 查当前字段 collation:
SHOW FULL COLUMNS FROM your_table,看Collation列 - 改单个字段(推荐,安全):
ALTER TABLE your_table MODIFY name VARCHAR(100) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci - 批量改整张表(慎用,大表会锁表):
ALTER TABLE your_table CONVERT TO CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci
最常被忽略的一点:字段 collation 才是 ORDER BY 和 WHERE 字符串比较的实际执行依据,库和表级设置只是“默认模板”,不碰旧结构。











