一聚教程网:一个值得你收藏的教程网站

最新下载

热门教程

如何修复MySQL因字符序不匹配导致的Illegal mix of collations?

时间:2026-06-19 08:56:03 编辑:袖梨 来源:一聚教程网

必须先定位再修改collation,否则易改错表、漏字段或继承旧默认值;执行三条SQL查库、表、列的排序规则,重点检查是否混用不同后缀的utf8mb4 collation。

查清 collation 混用的具体位置

不先定位就改,大概率改错表、漏字段,甚至让新字段继承旧库默认值。执行这三条语句快速摸清现状:

  • SELECT DEFAULT_COLLATION_NAME FROM information_schema.SCHEMATA WHERE SCHEMA_NAME = 'your_db_name';
  • SELECT TABLE_NAME, TABLE_COLLATION FROM information_schema.TABLES WHERE TABLE_SCHEMA = 'your_db_name';
  • SELECT COLUMN_NAME, COLLATION_NAME FROM information_schema.COLUMNS WHERE TABLE_SCHEMA = 'your_db_name' AND TABLE_NAME = 'your_table' AND COLLATION_NAME IS NOT NULL;

重点看结果里是否混着 utf8mb4_general_ciutf8mb4_unicode_ciutf8mb4_0900_as_cs 这类不同后缀的规则——只要参与 =INJOINUNION 的列 collation 不一致,1267 错误随时触发。

ALTER TABLE CONVERT TO 要慎用

CONVERT TO CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci 看似一步到位,但它会重写整张表,大表执行期间锁表、耗 I/O、可能拖垮线上服务。

更稳妥的做法是分层对齐:

  • 先改库级默认:ALTER DATABASE your_db_name CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
  • 再批量改表(仅改表定义,不重写数据):ALTER TABLE your_table ROW_FORMAT=DYNAMIC; + ALTER TABLE your_table CONVERT TO CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;(小表可直接用,大表建议拆成 MODIFY COLUMN 逐字段改)
  • 只改问题字段:ALTER TABLE your_table MODIFY COLUMN col_name VARCHAR(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;

别选 utf8mb4_general_ci——MySQL 8.0+ 已弃用,utf8mb4_unicode_ci 兼容性更稳,utf8mb4_0900_as_cs 区分大小写但需确认业务是否依赖该行为。

触发器和视图里必须显式 COLLATE

即使表和库全统一了,触发器仍可能报错。因为触发器执行时用的是会话级 @@collation_connection,不是字段本身的 collation。

在触发器中所有字符串操作都得加 COLLATE

  • IF NEW.name COLLATE utf8mb4_unicode_ci = 'admin' COLLATE utf8mb4_unicode_ci THEN
  • SET v_name = NEW.name COLLATE utf8mb4_unicode_ci;(变量声明也要带:DECLARE v_name VARCHAR(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
  • 函数参数不能漏:UPPER(NEW.name COLLATE utf8mb4_unicode_ci)

视图创建失败也常因 SELECT 中混了常量和字段:字符串字面量(如 'active')默认继承连接层 collation,必须写成 CONVERT('active' USING 'utf8mb4') COLLATE utf8mb4_unicode_ci 才能通过 CREATE VIEW 校验。

临时绕过别乱用 CONVERT

CONVERT(col USING 'utf8mb4') 只改字符集,不带 collation;返回类型是 CHAR,会导致索引失效、类型隐式转换、后续比较再次出错。

真正可控的临时方案是 COLLATE

  • WHERE t1.name COLLATE utf8mb4_unicode_ci = t2.name COLLATE utf8mb4_unicode_ci
  • SELECT ... FROM t1 JOIN t2 ON t1.id = t2.ref_id AND t1.code COLLATE utf8mb4_unicode_ci = t2.code COLLATE utf8mb4_unicode_ci

如果非得用 CONVERT,必须配 COLLATE:例如 CONVERT(col USING 'utf8mb4') COLLATE utf8mb4_unicode_ci,且注意长度截断风险——CONVERT(col AS CHAR(255) CHARACTER SET utf8mb4) COLLATE utf8mb4_unicode_ci 中的 255 必须 ≥ 字段实际最大长度。

最容易被忽略的是:连接层 collation 和客户端字符集不一致时,连 SET NAMES utf8mb4 都不一定生效,得在连接串里加 ?charset=utf8mb4 或执行 SET collation_connection = 'utf8mb4_unicode_ci'; 才能兜住源头。

热门栏目