Apache James 使用MySQL存储启动报错Specified key was too long; max key length is 3072 bytes

摘要:
修改数据源修改#Usederbyasdefault#database.driverClassName=org。阿帕奇。德比。jdbc。EmbeddedDriver#数据库。url=jdbc:derby:../var/store/deby;在conf/james数据库中。属性;create=true#数据库。用户名=app#数据库。密码=appdatabase.driverClassName=com.mysql.jdbc.Driverdatabase。url=jdbc:mysql://127.0.0.1:3306/james?org.apache.openjpa.persistence.PersistenceException:Specifiedkeywastoolong ; Maxkeylengthhis3072字节{stmnt2076356118CREATETABLEECAMES_MAIL_REPOSENGINE=innodb}[代码=1071,状态=42000]分析问题是否与教程中提到的问题类似。MySQL主键索引不够长,无法进行在线搜索。在找到大量信息后,我们知道MySQL的最大默认索引长度是767字节。如果是utf8代码。开始innodb_large_prefix=on之后的最大索引长度为3072字节。如果是utf8编码。日志中SQL显示字段的长度为1024。因此最长的varchar为4096˃3074。然而,当MySQL首次支持utf8时,它最多只支持3个字节。因此,在MySQL中,utf8mb4是真正的utf8。为了支持表情符号表达式,该公司在以前的项目中学习过MySQL的这个编码故事,所以喜欢在MySQL里使用utf8mb。
Apache James 使用mysql存储启动报错Specified key was too long; max key length is 3072 bytes

没事捣鼓自建mail服务,作为java开发,肯定想到了java实现。刚好apache就有开源的James(Java Apache Mail Enterprise Server)下载下来准备试试。

目前最新版是 3.4.0版本。

下载完成后网上找到教程进行配置。

因为针对mysql报错的问题。只记录数据源配置点。

修改数据源

修改conf/james-database.properties中

# Use derby as default
# database.driverClassName=org.apache.derby.jdbc.EmbeddedDriver
# database.url=jdbc:derby:../var/store/derby;create=true
# database.username=app
# database.password=app
database.driverClassName=com.mysql.jdbc.Driver
database.url=jdbc:mysql://127.0.0.1:3306/james?rewriteBatchedStatements=true&useUnicode=true&characterEncoding=utf8
database.username=james#账密自行修改即可
database.password=james
 
# Supported adapters are:
# DB2, DERBY, H2, HSQL, INFORMIX, MYSQL, ORACLE, POSTGRESQL, SQL_SERVER, SYBASE
# vendorAdapter.database=DERBY
vendorAdapter.database=MYSQL

因为教程中提示可能会报错,我提前在数据库中执行了下面脚本。

SET GLOBAL innodb_file_format = BARRACUDA;
SET GLOBAL innodb_large_prefix = ON;

报错

在bin目录下执行run.bat(win10)。

启动报错。

org.apache.openjpa.persistence.PersistenceException: Specified key was too long; max key length is 3072 bytes {stmnt 2076356118 CREATE TABLE JAMES_MAIL_REPOS (MAIL_REPO_NAME VARCHAR(1024) NOT NULL, PRIMARY KEY (MAIL_REPO_NAME)) ENGINE = innodb} [code=1071, state=42000]

分析

这个问题和教程中提到的类似,网上查找是MySQL主键索引长度不够。

找到很多资料后得知:mysql默认索引长度最大长度是767bytes,如果是utf8编码(MySQL的utf8编码最长3byte)。只能用varchar(255)。开启innodb_large_prefix=on后索引长度最大长度是3072bytes,如果是utf8编码。应该能用varchar(1024)。而日志中的sql显示字段长度为1024。理论上不应该报错。

解决

问题就在这编码上,按照上面的逻辑,字段长度乘以编码最大字节长度小于等于3072就可以。但是我使用的utf8mb4编码(MySQL独有的,最长4byte)。所以varchar(1024)最长就是4096>3074。我删除原来的数据库,以utf8重新创建,启动不再报错。

这里要吐槽一下,其实uft8编码字符理论上可以最多到6个字节长,通常uft8使用1~4字节为每个字符编码(utf8是变长编码-霍夫曼编码)。但是MySQL最开始支持utf8的时候只做了最长3个字节(MySQL中的uft8)。后面为了兼容4个字节,又增加了uft8mb4(旧版本没有)。所以其实MySQL中utf8mb4才是真正的utf8。之前公司项目中为了支持emoji表情(4字节utf8编码),了解过MySQL的这段编码故事,所以MySQL中喜欢使用utf8mb4。结果就遇到了这个坑爹的问题。

免责声明:文章转载自《Apache James 使用MySQL存储启动报错Specified key was too long; max key length is 3072 bytes》仅用于学习参考。如对内容有疑问,请及时联系本站处理。

上篇Java下拼接执行动态SQL语句(转)Entity Framework——执行sql语句下篇

宿迁高防,2C2G15M,22元/月;香港BGP,2C5G5M,25元/月 雨云优惠码:MjYwNzM=

相关文章

MySQL发展和技术选型——《MySQL DBA 工作笔记》

关于前言 作者在前言中提出的一些观点很具有参考价值, 梳理完整的知识体系 这是每一个技术流都应该追逐的,完整的知识体系能够使我们对知识的掌握更加全面,而不仅仅局限于点 建立技术连接的思维,面对需求,永远没有最好的数据库,只有最合适的业务场景 之前在读一本架构的书里也提到了类似的观点,技术的根本目的是为了业务服务的,不要为了技术而技术,而是应该跟着业...

详细分析MySQL的日志(一)

官方手册:https://dev.mysql.com/doc/refman/5.7/en/server-logs.html 不管是哪个数据库产品,一定会有日志文件。在MariaDB/MySQL中,主要有5种日志文件: 1.错误日志(error log):记录mysql服务的启停时正确和错误的信息,还记录启动、停止、运行过程中的错误信息。 2.查询日志(ge...

CentOS6.5卸载默认安装的mysql5.1,并安装mysql5.5(亲测有效)

感谢链接:https://jingyan.baidu.com/article/922554465e471a851648f4ed.html 指导。 1、安装前:CentOS6.5 yum 安装MySQL是5.1版本。老板觉得低了,好=》卸载,装上5.5的。 2、最终效果图:命令 select version(); 3、不废话,上代码和步骤: 第一步就是看l...

debezium关于cdc的使用(上)

博文原址:debezium关于cdc的使用(上) 简介 debezium是一个为了捕获数据变更(cdc)的开源的分布式平台。启动并指向数据库,当其他应用对此数据库执行inserts、updates、delete操作时,此应用快速得到响应。debezium是持久化和快速响应的,因此你的应用可以快速响应且不会丢失任意一条事件。debezium记录是数据库表的行...

MySql报错-Data truncation: Data too long for column 'XXX' at row 1

MySql报错-Data truncation: Data too long for column 'XXX' at row 1——墨问苍生 总结来说,Data truncation: Data too long for column 'CONTENT' at row 1问题的出现主要是以下几个原因: 1、可能 数据库中的字符集的编码与写代码的页面的编...

Mysql建表+创建索引

 创建表时可以直接创建索引,这种方式最简单、方便。其基本形式如下: CREATE TABLE 表名( 属性名 数据类型[完整性约束条件], 属性名 数据类型[完整性约束条件], ...... 属性名 数据类型 [ UNIQUE | FULLTEXT | SPATIAL ] INDEX | KEY [ 别名] ( 属性名1 [(长度)] [ ASC...