zoukankan      html  css  js  c++  java
  • Apache James 使用MySQL存储启动报错Specified key was too long; max key length is 3072 bytes

    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。结果就遇到了这个坑爹的问题。

  • 相关阅读:
    初识ES5、ES6
    WEB前端性能优化之三——JavaScript优化
    Web前端浏览器兼容问题
    HTML5新特性
    WEB前端性能优化之二——css优化
    WEB前端性能优化之一——网页级优化
    CSS的一些案例和坑
    bootstrap插件--select2.js--一个基于jQuery的替换框
    boostrap插件---typeahead.js---输入提示下拉菜单
    border-radius:50%,在安卓上存在兼容问题
  • 原文地址:https://www.cnblogs.com/jimmyfan/p/12673177.html
Copyright © 2011-2022 走看看