mysql 8.0+ 中 collation_server 是只读变量,启动后不可修改,其配置仅影响新连接的 collation_connection,新库/表默认排序规则由 character_set_server 对应的硬编码 collation(如 utf8mb4_0900_ai_ci)决定,字段级 collation 才真正决定排序行为。

MySQL 8.0+ 中,collation-server 配置仅影响连接初始化,不决定新库/表的默认排序规则;真正起作用的是 character_set_server 对应的硬编码默认 collation(如 utf8mb4_0900_ai_ci),无法通过配置文件覆盖。
为什么 SET GLOBAL collation_server 失败?
执行 SET GLOBAL collation_server = 'utf8mb4_unicode_ci' 会直接报错:Variable 'collation_server' is a read only variable。这不是权限问题,是 MySQL 8.0+ 的设计限制——该变量只接受启动时加载的值,运行时不可修改。
- 即使你有
SUPER权限,也改不了 - 在客户端里试了不生效,大概率是因为误以为它是可写变量
- 查
SHOW VARIABLES LIKE 'collation_server'发现还是旧值?先确认 mysqld 是否已重启
my.cnf 里配了 collation-server 却没用?
配置项 collation-server = utf8mb4_unicode_ci 写在 [mysqld] 段里确实能被读取,但它的实际作用非常有限:仅用于初始化新连接的 collation_connection,并不参与“新建数据库该用什么 collation”的决策逻辑。
- 必须同时设置
character-set-server = utf8mb4,否则collation-server可能被忽略 - 不要加引号,写成
utf8mb4_unicode_ci就行,不是'utf8mb4_unicode_ci' - 配置写在
[client]或[mysql]段下完全无效 - 改完必须重启服务:
sudo systemctl restart mysqld
新建数据库为什么不用你设的 collation?
MySQL 8.0+ 决定新数据库默认 collation 的方式是:查 character_set_server 值(比如 utf8mb4),然后硬编码选择该字符集的第一个可用 collation(即 utf8mb4_0900_ai_ci),根本不会看你写的 collation-server。
-
ALTER DATABASE db_name CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci只影响后续新建的表,已有表、字段、索引全部不变 - 执行后
SHOW CREATE DATABASE显示新值,但SHOW FULL COLUMNS FROM table_name里字段的Collation列仍是旧的 - 中文
ORDER BY name排序乱?问题出在字段定义上,不是库或服务器设置 - 要让排序生效,必须改字段级 collation:
ALTER TABLE t MODIFY name VARCHAR(100) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci
真正影响排序行为的地方只有字段级
MySQL 排序和比较行为最终由字段定义的 collation 决定,优先级是:字段 > 表 > 数据库 > 服务器。哪怕你把整个服务器设成 utf8mb4_zh_0900_as_cs,只要字段定义是 utf8mb4_0900_ai_ci,ORDER BY 就按后者走。
- 查字段当前 collation:
SHOW FULL COLUMNS FROM t,看Collation列 - 批量改整张表所有字符字段:
ALTER TABLE t CONVERT TO CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci(注意锁表) - 推荐精准修改单字段:
MODIFY或CHANGE,避免误动其他属性 - 用
utf8mb4_bin要小心——它区分大小写和重音,'A'和'a'不等,可能破坏现有业务逻辑
最常被忽略的一点:排序规则不是“开关”,而是字段定义的一部分;改完配置文件或数据库级别设置后,不碰字段,就等于什么都没改。线上大表改字段 collation 前,务必在从库或测试环境验证锁表现和排序结果。











