ALTER TABLE orders MODIFY user_id VARCHAR(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci; EXPLAIN SELECT o.id FROM orders o JOIN users u ON o.user_id = u.id;
两张表 join 报 1267 Illegal mix of collations (utf8mb4_general_ci,IMPLICIT) and (utf8mb4_0900_ai_ci,IMPLICIT),加个 collate 才能跑,执行计划却变成全表扫。先别急着动参数,把报错原文和时间点记下来,顺序反了容易白折腾。
原因不复杂,关联列排序规则不同时,数据库要把其中一侧转成能比较的规则,转换发生在列上,索引顺序被打乱。一端沿用老库的 general_ci,另一端是 8.0 默认的 0900_ai_ci,两边都对不上。
「排序规则不一致」排查到最后往往是很小的一处差异,前面那些复杂猜测可以先放一放。动手前把原文件复制一份带时间戳,出问题立刻换回去,比现场分析快得多。
一次只改一处,改完立刻验证,几个改动叠在一起,出问题就说不清是谁导致的。先做最小复现,能稳定跑出来的问题,排查成本会低一个数量级。
处理上按这个顺序:把两张表的关联列统一成同一个字符集和排序规则;改之前确认线上没有依赖旧规则的排序结果;用 modify 只改列 不重建整表;改完把 join 的 explain 再跑一遍。
改完只确认一件事:1267 不再出现 join 的 type 变成 ref key 显示关联列上的索引。
