MySQL 8.0升级后报Illegal mix of collations错误,因新表默认用utf8mb4_0900_ai_ci而老表仍为utf8mb4_general_ci,跨字段比较(如JOIN、FIND_IN_SET)时拒绝隐式转换;须用SHOW FULL COLUMNS等命令查实际collation,并通过ALTER TABLE MODIFY逐字段修正。

为什么utf8mb4_0900_ai_ci在升级后突然报错?
MySQL 8.0 默认把新表/新列的排序规则设为 utf8mb4_0900_ai_ci,但老表(从 5.7 迁入)字段实际还是 utf8mb4_general_ci。一旦查询里出现跨字段比较——比如 FIND_IN_SET()、JOIN、UNION 或子查询中混用新旧字段,MySQL 就拒绝隐式转换,直接抛出 ERROR 1267 (HY000): Illegal mix of collations。
怎么查清哪些字段还在用旧 collation?
别信 SHOW CREATE TABLE 输出里的注释,它可能只是“看起来”写了新 collation,但字段定义没改,就还是旧的。真实值得靠命令确认:
-
SHOW FULL COLUMNS FROM table_name LIKE 'col_name';—— 看Collation列实际值 -
SELECT @@collation_connection, @@collation_database;—— 查当前会话和库默认值 -
SELECT SCHEMA_NAME, DEFAULT_COLLATION_NAME FROM INFORMATION_SCHEMA.SCHEMATA WHERE SCHEMA_NAME = 'mysql';—— 检查系统库是否也卡在utf8mb4_general_ci
修复必须用ALTER TABLE MODIFY,不是改配置
改 my.cnf 里的 collation-server 或加 SET NAMES,只能影响新连接或临时语句,对已有字段无效。真正治本的操作是逐字段重定义:
- 普通字段:
ALTER TABLE t MODIFY col VARCHAR(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci; -
TEXT字段也要单独处理:MODIFY col TEXT CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci; - 如果字段有前缀索引(如
VARCHAR(500)只索引前 191 字符),注意utf8mb4_0900_ai_ci对索引长度计算更严格,可能需同步调小前缀长度 - 系统库不能漏:
ALTER DATABASE mysql COLLATE = utf8mb4_0900_ai_ci;,再确认mysql.user等关键表字段 collation 是否已同步
主从或降级场景下千万别硬扛utf8mb4_0900_ai_ci
如果你要把 8.0 的 dump 导入 5.7,或者做主从复制且从库是 5.7,utf8mb4_0900_ai_ci 必须被替换——5.7 根本不认识它,报 Unknown collation: 'utf8mb4_0900_ai_ci' 是必然结果。
- 安全替换目标是
utf8mb4_general_ci:5.7 原生支持,emoji 不丢,兼容性最稳 - 别替换成
utf8_general_ci:它绑定的是utf8(即utf8mb3)字符集,emoji 会截断 - grep 全文件定位三处关键位置:
CREATE DATABASE ... COLLATE、每个CREATE TABLE末尾、以及列定义后紧跟的COLLATE子句 - 从库
my.cnf里还得补上:collation-server = utf8mb4_general_ci和init_connect = 'SET NAMES utf8mb4 COLLATE utf8mb4_general_ci'
最容易被忽略的是:系统库 mysql 的 collation 不统一,会导致 MySQL 8.0 启动失败或 SQL 线程直接 abort;还有 TEXT 类型字段常被漏掉 MODIFY,一查才发现它还钉在旧 collation 上。











