← 中文资源

简体中文版本

MySQL ERROR 1071 — 指定的键过长

通过为长列建立前缀索引或缩短键的字节长度,修复 MySQL 1071——InnoDB 限制了索引键大小。

阅读英文原文

症状

错误“MySQL ERROR 1071 — 指定的键过长”指向一个明确的失效模式。下面依次给出症状、定位该原因的检查命令、根本原因、修复方案,以及证明修复有效的验证步骤。

可观察到的症状包括:

  • ERROR 1071 (42000): 指定的键过长;最大键长为 3072 字节
  • 对 VARCHAR 列添加复合唯一索引失败
  • latin1 下可用,切换到 utf8mb4 后失败

诊断

先在隔离环境中复现故障,再按顺序执行以下检查,逐步缩小范围。

步骤 1

mysql -e "CREATE TABLE t (a VARCHAR(1000), INDEX(a))"

错误会给出字节上限,其取决于行格式与列的字符集。

步骤 2

mysql -e "SHOW FULL COLUMNS FROM t\G" | grep -i collation

utf8mb4 解释了 4 倍乘数;更小的字符集或前缀索引可降低大小。

常见诱因(按出现频率排序):

  • 对整列建立索引的 VARCHAR 过大,超出索引键字节上限
  • utf8mb4 每字符最多 4 字节,使键大小翻数倍
  • 跨多个长列的复合索引合计超限

根因

InnoDB 将索引键限制为 3072 字节(DYNAMIC 行格式)。对宽 utf8mb4 VARCHAR 做整列索引可能超限,故 CREATE/ALTER 报 1071。

修复

为列建立前缀索引(INDEX(col(191))),在合适处选用更小字符集,为长值使用哈希列,并让复合键保持在字节预算内。

注意:前缀索引无法强制整列唯一,也不支持按完整值排序;使用前须核对语义。

ALTER TABLE users
  ADD INDEX idx_email (email(191));    -- prefix within byte budget

-- unique on full value via a generated hash column
ALTER TABLE users
  ADD COLUMN email_hash CHAR(64) AS (SHA2(email, 256)) STORED,
  ADD UNIQUE KEY uq_email_hash (email_hash);

-- check the resulting index
SHOW INDEX FROM users;

验证

用前缀重建索引并确认成功;运行 EXPLAIN 确认索引被预期查询使用。

修复后补充一条回归测试,复现原始症状,防止问题再次出现。

这类故障通常是环境问题而非纯逻辑错误,因此在缺陷记录中应写明完整命令、环境变量与工作目录。请用最小的脚本复现,待最小用例清楚后再扩大范围。为这类故障准备一份简短的排查清单,能显著减少下次排障时间。