直接改collation_server无效,必须先查清表和字段真实collation;5.7与8.0默认collation不同(utf8mb4_general_ci vs utf8mb4_0900_ai_ci),JOIN、FIND_IN_SET等操作会因collation不一致触发1267报错;治本需ALTER TABLE修改字段collation,临时加COLLATE仅绕过单条错误。

直接改 collation_server 配置不能解决报错,它只影响新连接的默认排序规则,对已有字段、JOIN、FIND_IN_SET 等操作完全无效。
查清表和字段的真实 collation 是第一步
错误不是凭空出现的,而是因为 5.7 创建的表用的是 utf8mb4_general_ci,8.0 新建表默认用 utf8mb4_0900_ai_ci,两者在比较时无法自动转换。你得先摸清现状:
- 执行
SHOW FULL COLUMNS FROM your_table;,看每列的Collation值 - 执行
SHOW CREATE TABLE your_table;,确认表级COLLATE和字段定义是否显式声明 - 特别注意
FIND_IN_SET()、UNION、JOIN ON这类隐式比较操作——它们会把两边字段的 collation 拿出来直接比,不走collation_server
ALTER TABLE 修改字段 collation 是治本动作
临时加 COLLATE utf8mb4_0900_ai_ci 到 SQL 里能绕过单条报错,但不解决数据层不一致。批量修复必须落到字段定义上:
- 用
ALTER TABLE t MODIFY col VARCHAR(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci;替换旧 collation - 如果字段是索引前缀(比如
VARCHAR(500)但只索引前 191 字符),要检查长度是否超限:utf8mb4_0900_ai_ci的索引长度计算更严格,可能需调小前缀长度 - 别漏掉
TEXT类型字段,它们也能带 collation,且同样参与比较
FIND_IN_SET 和 JSON_VALUE 报错必须显式统一 collation
FIND_IN_SET() 返回值默认继承第一个参数的 collation,而第二个参数(逗号分隔字符串)若来自不同 collation 的字段或变量,就会触发 Illegal mix of collations;JSON_VALUE() 在 8.0 中也要求显式声明返回类型与 collation:
- 写成
FIND_IN_SET(col1 COLLATE utf8mb4_0900_ai_ci, @var COLLATE utf8mb4_0900_ai_ci) - 虚拟列 + 索引写法已失效,必须改用
CREATE INDEX idx ON t (JSON_VALUE(data, '$.field' RETURNING CHAR(100) COLLATE utf8mb4_0900_ai_ci)) - 别依赖函数自动推导 collation,MySQL 8.0 对隐式转换更保守,宁可报错也不静默降级
跨版本导入时遇到 “Unknown collation” 错误怎么救
从 5.7 或更早导出的 SQL,在 MySQL 8.0 导入常卡在:Unknown collation: 'utf8mb4_unicode_520_ci' 或 COLLATION 'utf8_general_ci':
- 导出时加
--skip-set-charset --default-character-set=utf8mb4,避免写入旧 collation - 导入前用 sed 或脚本全局替换:把
utf8mb4_unicode_520_ci换成utf8mb4_0900_ai_ci,把utf8_general_ci换成utf8mb4_general_ci - 如果已导入失败,先
DROP DATABASE,再手动修正 SQL 文件后重试
最易被忽略的是:ALTER TABLE ... CONVERT TO CHARACTER SET 会重建整张表并锁表,大数据量下风险极高;而只改单个字段的 MODIFY 更安全,但必须完整写出字段类型和长度——漏写会导致默认值丢失或类型退化。


















