CakePHP 3在PhpMyAdmin创建i18n表遇1071错误,咨询编码切换
解决CakePHP 3 Translate Behavior创建i18n表时的1071索引长度错误
首先明确:不需要切换到utf8_general_ci,因为utf8_unicode_ci和utf8_general_ci都属于utf8编码(每个字符占3字节),切换编码无法解决索引长度超出限制的问题。下面来分析原因和具体解决方案:
错误原因
你遇到的1071 - Specified key was too long; max key length is 767 bytes错误,是因为InnoDB默认的索引键前缀长度限制为767字节。官方提供的SQL中,联合唯一索引I18N_LOCALE_FIELD包含四个字段:locale(varchar(6))、model(varchar(255))、foreign_key(int(10))、field(varchar(255))。按utf8编码计算,仅model字段就占255*3=765字节,加上locale的6*3=18字节,两者总和已经超过767字节,导致索引创建失败。
可行解决方案
方案1:缩短索引字段的长度
修改model和field字段的长度为191(varchar(191)),因为191*3=573字节,这样联合索引的总长度会控制在767字节以内。调整后的SQL如下:
CREATE TABLE i18n ( id int NOT NULL auto_increment, locale varchar(6) NOT NULL, model varchar(191) NOT NULL, foreign_key int(10) NOT NULL, field varchar(191) NOT NULL, content text, PRIMARY KEY (id), UNIQUE INDEX I18N_LOCALE_FIELD(locale, model, foreign_key, field), INDEX I18N_FIELD(model, foreign_key, field) );
这个方案不需要修改数据库配置,适合无法调整MySQL配置的场景。191的长度对于大多数项目来说已经足够存放模型名和字段名。
方案2:开启InnoDB大前缀支持
如果需要保留varchar(255)的长度,可以通过修改MySQL配置来支持更长的索引:
- 编辑MySQL配置文件(
my.cnf或my.ini),添加以下配置:
innodb_file_format = Barracuda innodb_file_per_table = 1 innodb_large_prefix = 1
- 重启MySQL服务。
- 创建表时指定
ROW_FORMAT=DYNAMIC(或COMPRESSED),调整后的SQL:
CREATE TABLE i18n ( id int NOT NULL auto_increment, locale varchar(6) NOT NULL, model varchar(255) NOT NULL, foreign_key int(10) NOT NULL, field varchar(255) NOT NULL, content text, PRIMARY KEY (id), UNIQUE INDEX I18N_LOCALE_FIELD(locale, model, foreign_key, field), INDEX I18N_FIELD(model, foreign_key, field) ) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci ROW_FORMAT=DYNAMIC;
这个方案可以保留原字段长度,但需要有修改MySQL配置的权限。
关于utf8_unicode_ci vs utf8_general_ci的补充
两者的核心区别在于排序规则:
utf8_unicode_ci遵循Unicode标准排序,排序更准确,但性能略低;utf8_general_ci排序规则简化,性能稍快,但对于某些语言(如德语、法语)的排序不够准确。
但如前所述,切换到utf8_general_ci并不能解决当前的索引长度问题,所以不建议为了这个错误切换编码。
内容的提问来源于stack exchange,提问作者Chris Carton
相关产品推荐
相关产品推荐

