错误源于innodb索引字节超限:utf8mb4下varchar(255)达1020字节>767字节限制;mysql 5.7前默认innodb_large_prefix=off且row_format=compact,须设on并改dynamic格式方可支持3072字节。

“Specified key was too long” 是 InnoDB 索引字节长度超限
Navicat 保存索引时报错 Specified key was too long; max key length is 767 bytes,说明你正在用 utf8mb4 字符集创建一个单列索引(比如主键或唯一索引),而该字段定义的字符数 × 4(utf8mb4 最大每字符 4 字节)超过了 767 字节。例如 VARCHAR(255) 在 utf8mb4 下理论最大占 1020 字节,直接超限。
- MySQL 5.7 及之前默认
ROW_FORMAT=COMPACT,且innodb_large_prefix=OFF,强制索引前缀上限为 767 字节 - MySQL 8.0 默认已启用
innodb_large_prefix=ON,但前提是表格式为DYNAMIC或COMPRESSED,否则仍卡在 767 - 错误不发生在 Navicat 客户端校验层,而是 MySQL 服务端真实拒绝建索引,所以改 Navicat 设置无效
为什么有时报 1000 字节,有时报 767?
报 1000 bytes 通常是云数据库(如阿里云 RDS、腾讯云 CDB)做了定制限制,或旧版 MySQL + MyISAM 引擎(MyISAM 默认索引上限是 1000 字节);而本地原生 MySQL 5.6+ InnoDB 报 767 是标准行为。别被数字带偏——核心都是「索引字段总字节数超了引擎当前配置允许的上限」。
- 查当前限制:执行
SHOW VARIABLES LIKE 'innodb_large_prefix';和SHOW TABLE STATUS LIKE 'your_table';看Row_format - 查实际索引长度:用
SELECT COLUMN_NAME, CHARACTER_MAXIMUM_LENGTH, COLLATION_NAME FROM INFORMATION_SCHEMA.COLUMNS WHERE TABLE_NAME = 'your_table' AND COLUMN_NAME IN ('col1', 'col2');结合字符集估算字节数 - 注意复合索引:
(name, email)的总长 =name最大字节数 +email最大字节数,不是字符数相加
快速修复:三步改配置 + 重建表
临时绕过不可取,必须让 InnoDB 允许长索引。以下操作需有 SUPER 权限,且必须在服务端执行(Navicat 设计界面点保存前改不了):
- 确认并设置参数:
SET GLOBAL innodb_large_prefix = ON;(MySQL 5.6.3–5.7.7 需同时设innodb_file_format=Barracuda和innodb_file_per_table=ON) - 修改表格式:
ALTER TABLE your_table ROW_FORMAT=DYNAMIC;(这步最关键,COMPACT 格式不认 large_prefix) - 重建索引(或删掉再建):
ALTER TABLE your_table DROP INDEX idx_name, ADD UNIQUE INDEX idx_name (long_column);
改完立刻生效,但要注意:如果表里已有数据且含超长值,重建索引时可能触发 Data too long for column,得先清理或截断异常数据。
真正容易被忽略的点
即使开了 innodb_large_prefix 和 DYNAMIC,如果你的索引字段用了函数表达式(如 INDEX((SUBSTRING(title, 1, 200)))),MySQL 8.0.13+ 才支持函数索引,低版本会静默退化为前缀索引并再次超限;另外,Navicat 自动生成的建表语句若没显式写 ROW_FORMAT=DYNAMIC,新表仍可能沿用 COMPACT,导致下次加索引又崩——别依赖工具默认,自己写 DDL 时加上这一行最稳。











