【踩坑日记】-解决Specified key was too long; max key length is 1000 bytes

912 阅读2分钟

持续创作,加速成长!这是我参与「掘金日新计划 · 6 月更文挑战」的第3天,点击查看活动详情

问题描述

相信很多同学在日常开发中都接触过JPA或者Mybatis。有的偏爱JPA有的偏爱Mybatis。 它们其中一个不同点就是JPA在项目启动时支持配置DDL策略。但是在项目开发中偶尔出现配置了DDL,但是没按照自己预期生成表结构的,此时需要检查控制台异常,看具体报错内容。今天示范的是ddl-auto配置的update,但是在启动项目后,新增的表结构并没有自动写入指定数据库中。报错时提示Specified key was too long; max key length is 1000 bytes

image.png

相关知识

DDL策略

  • create 每次启动项目都是新建表(表中原来的数据会被清空)
  • create-drop 启动项目时新建表结构,销毁项目时删除表结构(表中原来的数据会被清空)
  • update 启动项目时创建数据库中没有的表结构(原本存在的表数据和结构不发生删减只有新增)
  • validate 将数据库中的表结构和代码中的字段进行校验,不对实际表结构产生影响,校验失败会报错(表中原来数据无影响)
  • none 启动时没有任何操作

综上,在生产环境中应用最多的就是update,要慎用create和create-drop,防止正式环境数据被删除。

MySQL字符集所占用的字节

  • 使用SELECT * FROM information_schema.CHARACTER_SETS;查看一下数据库具体编码方式和对应的位数。
  • 一般使用的是utf8、utf8mb4,一般项目大多选择后者,后者可以存储的范围更大,可以存储如表情包、日文、韩文的字符串,而如果使用前者的话会出现乱码的情况。 image.png

问题分析

指定的键长度太大,但是我看了下执行语句,主键长度就255。而所使用的数据库默认是utf8mb4,所以当字段类型是varchar(255)类型时,它实际所占用的字节为255*4>1000。

解决方案

找到问题后就有3种解决方案

  • 修改编码方式
  • 修改索引最大长度
  • 修改引擎 使用语句SELECT@@global.innodb_large_prefix;查看innodb引擎是否开启允许索引列最大长度达到3072 如果没有开启,则执行语句SET GLOBAL innodb_large_prefix = ON;开启 我选择的是修改语句默认引擎,所以在JPA的配置文件中增加配置
spring:
    jpa:
        database-platform: org.hibernate.dialect.MySQL5InnoDBDialect

将默认引擎修改为innodb