MySQL切换至utf8mb4遇1071错误:指定键长度超出限制
解决MySQL utf8转utf8mb4时的1071索引过长错误
哥们儿,我太懂你这个坑了——当初我把表从utf8转utf8mb4的时候,也被这个1071错误卡了好久,网上多数方案只说新建索引,根本没提怎么处理已经存在的索引,简直坑人!先给你理清楚根源,再一步步教你搞定:
为什么会报错?
utf8mb4字符集下,每个字符最多占4字节(而旧的utf8最多占3字节)。如果你的表上有索引(主键、唯一索引、普通索引)的字段是varchar类型,长度设得比较大(比如常见的255),那索引的字节长度就会超过MySQL的限制:
- MyISAM引擎默认索引最大长度是1000字节
- InnoDB引擎默认是767字节(开启
innodb_large_prefix后能到3072字节)
比如varchar(255)在utf8mb4下是255×4=1020字节,刚好超过MyISAM的1000字节限制,直接触发1071错误。
具体解决步骤(分场景)
场景1:字段可以缩短长度(最简单)
如果你的varchar字段不需要存255个字符,直接缩短到符合字节限制的长度:
- MyISAM:最多设为250(250×4=1000字节)
- InnoDB:最多设为191(191×4=764字节,低于767限制)
操作步骤:
- 先删除现有索引(不删的话改字段会报错):
ALTER TABLE your_table DROP INDEX index_name; -- 如果是主键的话用:ALTER TABLE your_table DROP PRIMARY KEY; - 修改字段的字符集和长度:
-- MyISAM用这个 ALTER TABLE your_table MODIFY COLUMN your_column VARCHAR(250) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci; -- InnoDB用这个 ALTER TABLE your_table MODIFY COLUMN your_column VARCHAR(191) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci; - 重新创建索引:
ALTER TABLE your_table ADD INDEX index_name(your_column); -- 主键的话:ALTER TABLE your_table ADD PRIMARY KEY(your_column);
场景2:字段必须保留原长度(用前缀索引)
如果字段必须存255个字符,那就用前缀索引——只对字段的前N个字符建索引,N满足N×4 ≤ 引擎的索引长度限制:
- MyISAM:N≤250
- InnoDB:N≤191
操作步骤:
- 删除现有索引:
ALTER TABLE your_table DROP INDEX index_name; - 修改字段字符集(保留原长度):
ALTER TABLE your_table MODIFY COLUMN your_column VARCHAR(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci; - 创建前缀索引:
-- MyISAM用这个 ALTER TABLE your_table ADD INDEX index_name(your_column(250)); -- InnoDB用这个 ALTER TABLE your_table ADD INDEX index_name(your_column(191));
场景3:InnoDB引擎想保留完整长度索引(进阶)
如果是InnoDB引擎,你可以开启innodb_large_prefix参数,把索引长度限制提升到3072字节,这样varchar(767)都能建完整索引:
- 先检查参数状态:
SHOW VARIABLES LIKE 'innodb_large_prefix'; SHOW VARIABLES LIKE 'innodb_file_format'; - 如果没开启,先设置(需要有全局权限,生产环境建议先测试):
(永久生效需要修改my.cnf/my.ini,添加这两行后重启MySQL)SET GLOBAL innodb_large_prefix = ON; SET GLOBAL innodb_file_format = Barracuda; - 修改表的行格式为DYNAMIC或COMPRESSED:
ALTER TABLE your_table ROW_FORMAT=DYNAMIC; - 最后修改字段字符集并重建索引:
ALTER TABLE your_table MODIFY COLUMN your_column VARCHAR(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci, ADD INDEX index_name(your_column);
重要提醒
- 操作前一定要备份表!用这个命令:
mysqldump -u your_username -p your_database your_table > backup_your_table.sql - 生产环境大表操作建议用
pt-online-schema-change或gh-ost工具,避免锁表影响业务 - 确认你的应用程序、数据库连接都配置了utf8mb4字符集,不然会出现乱码
内容的提问来源于stack exchange,提问作者Mitya
相关产品推荐
相关产品推荐

