解决MySQL Specified key was too long; max key length is 767 bytes

最近在给QA测试环境数据表的一个的 varchar(255) 类型字段添加索引时遇到了错误Specified key was too long; max key length is 767 bytes,奇怪的是同样的创建索引命令是可以在开发环境执行成功的。
我们知道InnoDB引擎索引字段长度不能超过767,所以在排查问题时,我的第一反应是数据表的字符集配置有问题。

  • utf8mb4 字符集是 1个字符=4个字节, varchar255字节长度 = 255 * 4=1020字节
  • utf8 字符集是 1个字符=3个字节, varchar255字节长度 = 255 * 3= 765字节
  • gbk字符集是 1个字符=2个字节, varchar255字节长度 = 255 * 2= 510字节

检查了数据表,果然字符集配置是utf8mb4,255个字符需要1020个字节,报错是符合预期的。但是实际使用中,该列是用来存储固定64字符长的token的,就算是utf8mb4 字符集,64 * 4 = 256字节也是远远小于767的,按理不应该报错。

并且开发环境同样的数据表配置并没有出现问题,会不会是脏数据(超过64字符)引起的呢?
于是使用下面命令按列的长度排序,找出前5条数据,发现查出的列长度都是64,确定不是脏数据引起的问题。

SELECT 列名 FROM 表名 ORDER BY length(列名) DESC limit 5;

再次查看数据表,show create table 表名;,对比两个环境的数据表有什么差异,一个属性引起了我的注意。
原来QA环境该表的row_format属性不知为何被改为了compact。

image.png

row_format为compact时,不论实际数值长度为多少,创建索引时都按照数据列声明长度创建,如上文所提,255字符也就是需要1020字节,难怪会报错。
找到问题后修复就很简单了,将row_format改为Dynamic,即按照值的实际长度而非声明长度创建索引。

alter table 表名 row_format=Dynamic;

参考:
https://cloud.tencent.com/developer/article/1005696
https://stackoverflow.com/questions/1814532/1071-specified-key-was-too-long-max-key-length-is-767-bytes

你可能感兴趣的:(解决MySQL Specified key was too long; max key length is 767 bytes)