mysql索引长度按字节计算而非字符数,utf8mb4下varchar(255)达1020字节,超默认767字节限制;联合索引三字段相加3060字节更易触发错误,应优先缩减字段长度、使用前缀索引或调整row_format=dynamic。

为什么utf8mb4字段建索引容易超767字节
不是字段声明的字符数超了,而是数据库按字节算索引长度。比如 varchar(255) 在 utf8mb4 下最多占 255 × 4 = 1020 字节——单列就超了默认的 767 字节限制。联合索引更危险:registry_group、registry_key、registry_value 三个 varchar(255) 加起来就是 3060 字节,远超上限。
直接改字段长度是最稳妥的修复方式
别碰配置参数,先看业务是否真需要那么长的索引字段。很多场景下,前缀就能满足区分需求:
-
registry_key实际值通常远短于 255,改成varchar(191)就刚好卡在191 × 4 = 764字节内 - 联合索引里保留高区分度字段,删掉低价值长字段,比如去掉
registry_value(它一般存 IP 或 host,没必要参与索引) - 如果字段必须长(如 URL),用前缀索引:
ALTER TABLE xxl_job_registry ADD INDEX i_g_k_v (registry_group, registry_key(64), registry_value(64));
ROW_FORMAT=DYNAMIC 是 MySQL 5.7+ 必须配的开关
就算开了 innodb_large_prefix=ON,表的行格式还是 COMPACT 的话,767 字节限制照旧生效。检查当前表格式:
SHOW TABLE STATUS LIKE 'xxl_job_registry';
如果 Row_format 是 Compact,必须改:
ALTER TABLE xxl_job_registry ROW_FORMAT=DYNAMIC;
注意:这个操作会锁表,线上执行前评估影响;MySQL 8.0 默认支持 3072 字节,但依然依赖该设置。
别轻易改字符集降级到 utf8
utf8(实际是 utf8mb3)虽然每字符最多 3 字节,能多塞点字段进索引,但它不支持 emoji 和部分生僻 Unicode 字符。2026 年还在用 utf8 的系统,大概率会在某次用户输入 ? 或 ?? 时突然崩掉。真要省字节,优先砍字段、加前缀、调行格式,而不是退字符集。











