ERROR 1071索引超限因utf8mb4下VARCHAR(255)超767字节限制,需启用innodb_large_prefix、改用DYNAMIC行格式或缩字段至VARCHAR(191);改排序规则须显式指定COLLATE;连接层collation不匹配会导致索引失效。

ALTER TABLE CONVERT TO 失败报错 ERROR 1071:索引长度超限
常见于把 utf8 表转成 utf8mb4 时直接用 CONVERT TO CHARACTER SET utf8mb4,尤其字段是 VARCHAR(255) 这类长文本。MySQL 5.7 默认 InnoDB 单列索引前缀限制是 767 字节,utf8mb4 下每个字符最多占 4 字节,255 × 4 = 1020 > 767,直接报错。
这不是字符集“非法”,而是索引物理限制触发的失败。解决路径不是降级字符集,而是绕过前缀限制:
- 启用
innodb_large_prefix(MySQL 5.7.7+ 默认已开,但需确认表使用ROW_FORMAT=DYNAMIC或COMPRESSED) - 改字段长度:比如
MODIFY column_name VARCHAR(191)(191 × 4 = 764 ≤ 767) - 删掉原索引再改字段,避免 ALTER 同时重建索引触碰限制
SHOW CREATE TABLE 显示 COLLATE 不一致,但 ALTER MODIFY 不生效
执行 ALTER TABLE t MODIFY name VARCHAR(50) CHARACTER SET utf8mb4 后,SHOW FULL COLUMNS 里 Collation 列还是 utf8mb4_general_ci,而目标是 utf8mb4_0900_as_cs——这是因为只改 CHARACTER SET 不等于改 COLLATE,MySQL 不会自动同步排序规则。
必须显式带 COLLATE:
ALTER TABLE t MODIFY name VARCHAR(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_as_cs;
注意点:
- 如果字段有索引,
MODIFY会重建索引,大表操作耗时且锁表 - 不能只写
COLLATE xxx而不写CHARACTER SET,否则报错 - 批量改多个字段,用逗号分隔写在一条语句里,减少 DDL 次数
客户端连接层未声明 collationConnection,导致建索引语句本身被隐式转换
你执行 CREATE INDEX idx ON t (name),但连接的 @@collation_connection 是 latin1_swedish_ci,而字段 name 的 COLLATION 是 utf8mb4_0900_as_cs。MySQL 在解析建索引语句时,会尝试把字符串字面量(比如索引名、注释)按连接层规则处理,若不匹配,可能拒绝创建或建出异常索引。
验证方式:
SELECT @@collation_connection, @@character_set_client;
修复动作:
- 连接串加参数:
?useUnicode=true&characterEncoding=utf8mb4&collationConnection=utf8mb4_0900_as_cs - 连接后立即执行:
SET NAMES utf8mb4 COLLATE utf8mb4_0900_as_cs; - Java 应用确保
mysql-connector-java≥ 8.0.23,旧版默认不传collationConnection
EXPLAIN 显示 key 为空,但 SHOW INDEX 确认索引存在
这说明索引“建成功了”,但查询时没被选中——根本原因不是创建失败,而是运行时因字符集/排序规则不一致触发隐式转换,让 MySQL 主动弃用索引。
关键排查顺序必须是:
- 查字段实际
Collation:SHOW FULL COLUMNS FROM t LIKE 'name'; - 查当前连接
@@collation_connection - 查 SQL 中字面量隐含的 collation:
SELECT COLLATION('张三');(返回值必须和字段一致) - JOIN 场景下,两边字段
Collation必须完全相同,差一个下划线都不行(如utf8mb4_0900_ai_civsutf8mb4_0900_as_cs)
最麻烦的是它不报错,只默默变慢。别信“索引建了就行”,得每一层都对齐。


















