mysql错误1267是collation不一致触发的硬性报错,必须使参与=、in、join、union或concat的列或表达式使用完全相同的排序规则;需用三句sql查库、表、字段collation分布,重点比对utf8mb4不同后缀规则是否混用,并优先统一数据库默认collation再逐级调整。

这不是字符集问题,是 collation 不一致触发的硬性报错,只要参与 =、IN、JOIN、UNION 或 CONCAT 的列或表达式 collation 不同,MySQL 就会直接抛出错误 1267。
查清哪几处 collation 对不上
别靠猜,先用三句 SQL 把库、表、字段级的 collation 分布摸清楚。错误信息里写的两个 collation(比如 utf8mb4_0900_ai_ci 和 utf8mb4_unicode_ci)只是表层线索,实际冲突点可能藏在函数返回值、临时表、甚至会话变量里。
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 IN ('t1', 't2') AND COLLATION_NAME IS NOT NULL;
重点看结果里是否混着 utf8mb4_general_ci、utf8mb4_unicode_ci、utf8mb4_0900_as_cs、utf8mb4_german2_ci 这类不同后缀的规则——它们彼此不兼容,不能自动对齐。
ALTER TABLE CONVERT TO 要慎用,大表会锁死
ALTER TABLE t CONVERT TO CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci 看似省事,但它会重写整张表、重建所有索引、全程加写锁。一张千万行的表执行几分钟到几小时都有可能,线上服务直接卡住。
- 它只改当前表,不改变数据库默认
collation,后续新建字段仍可能继承旧值 -
CONVERT TO会把所有VARCHAR/TEXT字段都带上新collation,但ENUM/SET不受影响,容易漏掉 - 如果某列原始是
latin1_swedish_ci,而数据实际是 GBK 编码,直接CONVERT TO会导致乱码 - 生产环境建议加
ALGORITHM=INPLACE, LOCK=NONE(MySQL 5.6+),但不是所有场景都支持,得先EXPLAIN FORMAT=TREE验证
COLLATE 强制指定只适合临时救急
当无法动表结构(比如第三方库、只读实例、灰度未全量),SQL 层加 COLLATE 是最快路径,但必须两边都加,且选型要匹配业务语义。
-
JOIN场景:ON t1.name COLLATE utf8mb4_unicode_ci = t2.name COLLATE utf8mb4_unicode_ci -
UNION场景:SELECT col1 COLLATE utf8mb4_unicode_ci FROM t1 UNION SELECT col2 COLLATE utf8mb4_unicode_ci FROM t2 - 子查询中函数返回值也得对齐:
WHERE cInvName COLLATE utf8mb4_unicode_ci IN (SELECT SUBSTRING_INDEX(FileName, '.', 1) COLLATE utf8mb4_unicode_ci FROM fileinfo) - 触发器里尤其危险:即使表已统一,
IF NEW.name = 'admin'仍可能报错,因为会话级@@collation_connection可能和字段collation不一致,必须显式补COLLATE
优先改数据库默认 collation,再逐级下沉
最稳的路径是「库 → 表 → 字段」自上而下对齐,避免改完表又因库默认值不对,导致新字段继续混入旧 collation。
- 先改库:
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; - 只改问题字段更安全:
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区分大小写,除非业务明确依赖,否则慎用
真正麻烦的是那些隐式生成的 collation:函数返回值(如 SUBSTRING_INDEX)、临时表、用户变量、甚至 JDBC 驱动传参时的会话设置。这些地方不会出现在 information_schema.COLUMNS 里,但一样会触发 1267。











