美文网首页
解决MySQL Specified key was too lo

解决MySQL Specified key was too lo

作者: 李小西033 | 来源:发表于2021-05-01 21:45 被阅读0次

    最近在给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 lo

          本文链接:https://www.haomeiwen.com/subject/galzrltx.html