必须现场查字段Collation和@@collation_connection是否完全一致:SHOW FULL COLUMNS确认字段真实排序规则,SELECT @@collation_connection查执行时字符串解析规则,二者不匹配即触发隐式转换导致索引失效。

查清字段和连接层的 COLLATION 是否真正一致
索引失效不报错,只悄悄变慢,根源常是字段定义的 COLLATE 和当前连接的 @@collation_connection 不匹配。别信配置文件或文档,必须现场查:
-
SHOW FULL COLUMNS FROM users LIKE 'name';—— 看输出中Collation列,确认字段真实排序规则 -
SELECT @@collation_connection, @@character_set_client;—— 这是 SQL 执行时字符串字面量默认按什么规则解析 - 如果字段是
utf8mb4_unicode_ci,而@@collation_connection是utf8mb4_0900_as_cs或latin1_swedish_ci,就已埋下隐式转换伏笔
用 EXPLAIN 验证是否真走索引,重点盯 key 和 type
执行计划里藏了最直接证据。只要出现以下任一现象,基本可断定字符集/排序规则不一致触发了隐式转换:
-
key为NULL,哪怕该列明明建了索引 -
type是ALL或index,而非ref、eq_ref - 在 JOIN 场景下,
Extra出现Using where; Using join buffer (Block Nested Loop),说明无法用索引驱动关联
检查 WHERE 条件中字符串值是否被当数字处理
这是最常见也最容易忽略的触发点:varchar 字段传入无引号数字,MySQL 会逐行调用 CAST(phone AS SIGNED),B+ 树索引彻底失效。
- 错误写法:
WHERE phone = 13800138000(phone 是VARCHAR) - 正确写法:
WHERE phone = '13800138000' - MyBatis 中禁用
${}拼接,一律用#{}——否则引号根本不会生成 - 上线前对所有含字符串字段的查询跑一遍
EXPLAIN,尤其关注日志里硬编码的 SQL
主从环境要单独验证复制线程的 collation_connection
主库上好好的查询,到了从库就变慢甚至卡住,很可能是复制线程自身连接参数不对。它不是普通客户端,但同样受 @@collation_connection 控制:
- 在从库执行:
SELECT @@collation_connection;,不是看应用连接,是看复制线程当前用的啥 - 若返回
latin1_swedish_ci,而字段是utf8mb4_unicode_ci,那重放 binlog 时就会强制转换 - 修复方式不是改 SQL,而是从库启动参数加
--collation-server=utf8mb4_unicode_ci,或启动后执行SET NAMES utf8mb4 COLLATE utf8mb4_unicode_ci;
rows 从 1 跳到几万。真正关键的不是“有没有 utf8mb4”,而是字段、连接、复制线程这三层的 COLLATE 值是否一字不差。漏掉一层,索引就掉一层。


















