必须现场查字段、连接层、sql字面量三层collation是否完全一致,不一致必触发隐式转换导致索引失效;用show full columns查字段collation,select @@collation_connection查连接层,explain看key是否为null及type是否为all来验证。

直接查三层 COLLATION 是否完全一致,不一致就必然触发隐式转换,索引悄悄失效——它不报错,只变慢。
查字段真实 COLLATION 用 SHOW FULL COLUMNS
别信建表语句或文档,字段当前实际用的排序规则,只能现场查:
-
SHOW FULL COLUMNS FROM users LIKE 'name';—— 看输出中Collation列值,比如utf8mb4_0900_as_cs - 如果字段是
VARCHAR但Collation是latin1_swedish_ci,而其他表同名字段是utf8mb4_unicode_ci,JOIN 或 WHERE 就可能出问题 -
SHOW CREATE TABLE users;可辅助确认表级默认值是否干扰了单个字段定义
查连接层 COLLATION 用 SELECT @@collation_connection
应用连上来那一刻,@@collation_connection 决定了 '张三' 这种字符串字面量按什么规则解析:
-
SELECT @@collation_connection, @@character_set_client;—— 必须和字段的Collation完全相同(注意:utf8mb4_unicode_ci≠utf8mb4_0900_as_cs) - JDBC 连接串漏掉
collationConnection=utf8mb4_0900_as_cs,哪怕表和字段都改对了,查询仍走全表扫描 - 主从复制线程也有自己的
@@collation_connection,从库上执行该命令,不是看应用连接,是看 binlog 重放时用的啥
用 EXPLAIN 验证是否真失效
执行计划里藏了最硬的证据,盯住这三项:
-
key为NULL,哪怕该列明明有索引 -
type是ALL或index,而不是ref、eq_ref -
Extra出现Using where; Using join buffer (Block Nested Loop)—— JOIN 无法用索引驱动,说明两边字段 COLLATION 不兼容
ALTER TABLE 修改必须同时指定 CHARACTER SET 和 COLLATE
只改字符集或只改排序规则,等于没改:
- 错误写法:
ALTER TABLE users CONVERT TO CHARACTER SET utf8mb4;—— 不动已有字段的COLLATE - 错误写法:
ALTER TABLE users MODIFY name VARCHAR(50) COLLATE utf8mb4_0900_as_cs;—— 漏了CHARACTER SET,MySQL 可能 fallback 到默认值 - 正确写法:
ALTER TABLE users MODIFY name VARCHAR(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_as_cs; - 改完立刻
SHOW CREATE TABLE users;验证字段定义里是否同时出现CHARACTER SET utf8mb4和COLLATE utf8mb4_0900_as_cs
最容易被忽略的是:三者(字段 COLLATION、连接 COLLATION、SQL 字面量隐含 COLLATION)必须一字不差。漏一层,EXPLAIN 里的 key 就永远是 NULL。











