错误:指定的密钥太长;最大密钥长度为 1000 字节

2024-01-20

Error:

1071 - 指定的密钥太长;最大密钥长度为 1000 字节

CREATE TABLE `phppos_modules_actions` (
  `action_id` VARCHAR( 255 ) CHARACTER SET utf8 COLLATE utf8_unicode_ci NOT NULL ,
  `module_id` VARCHAR( 255 ) CHARACTER SET utf8 COLLATE utf8_unicode_ci NOT NULL ,
  `action_name_key` VARCHAR( 255 ) CHARACTER SET utf8 COLLATE utf8_unicode_ci NOT NULL ,
  `sort` INT NOT NULL ,
  PRIMARY KEY ( `action_id` , `module_id` )
) ENGINE = INNODB CHARACTER SET utf8 COLLATE utf8_unicode_ci;

我知道错误是由于 255x2x3 (每个字符 3 个字节)而发生的

并非所有安装都会发生这种情况。我可以更改什么设置?


NO_ENGINE_SUBSTITUTION 禁用且 INNODB 未激活,这是一个糟糕的组合

  • 到 MySql 5.5 为止,sqlmode 默认值为空字符串,这意味着默认情况下未设置 sqlmode NO_ENGINE_SUBSTITUTION

根据 MySql 文档(参见https://dev.mysql.com/doc/refman/5.6/en/sql-mode.html#sqlmode_no_engine_substitution https://dev.mysql.com/doc/refman/5.6/en/sql-mode.html#sqlmode_no_engine_substitution)这就是sqlmode NO_ENGINE_SUBSTITUTION的含义:

控制默认存储引擎的自动替换 CREATE TABLE 或 ALTER TABLE 等语句指定存储 引擎被禁用或未编译。

因为存储引擎在运行时是可插拔的,不可用 引擎的处理方式相同:

禁用 NO_ENGINE_SUBSTITUTION 时,对于 CREATE TABLE 使用默认值 使用引擎,如果所需引擎被使用,则会出现警告 不可用。对于 ALTER TABLE,出现警告并且表不存在 改变了。

启用 NO_ENGINE_SUBSTITUTION 后,会发生错误并且表 如果所需的引擎不可用,则不会创建或更改。

  • 所以:如果 NO_ENGINE_SUBSTITUTION 被禁用并且 INNODB 被关闭,如果您在 CREATE TABLE 语句中指定 INNODB,MySql 也会切换到 MYISAM。
  • 如果您正在创建的表适用于 MYISAM,您只会收到一条警告,并且该表将被创建。这不是你的情况,你的创建语句中包含的索引超出了MYISAM的1000字节限制,那么创建失败,错误1071报告MYISAM错误。那是因为工作引擎是MYISAM,而不是INNODB。

PROOF

MySql 版本 5.1.56 社区

Case 1:

Options in my.cnf  
sql-mode=""  
default-storage-engine=MYISAM  
skip-innodb uncommented (without#) 

Return on execution of your create statement:
Error Code: 1071. Specified key was too long; max key length is 1000 bytes

Explanation: INNODB is not active, the engine is automatically switched to MYISAM  
that returns this error as they key is longer than MYISAM 1000 bytes limit.  
The key length is: 
2 fields x 255 char x 3 bytes utf8 encoding + 2 x 1 length byte = 1532 bytes   

Case 2:

Options in my.cnf
sql-mode="NO_ENGINE_SUBSTITUTION"
default-storage-engine=MYISAM
skip-innodb uncommented (without#)

Return on execution of your create statement:
Error Code: 1286. Unknown table engine 'INNODB'

Explanation: INNODB is not active but the engine substitution is not permitted
by sql mode therefore the DB returns an error about the attempt of using a disabled engine. 

Case 3:

Options in my.cnf
sql-mode="NO_ENGINE_SUBSTITUTION"
default-storage-engine=MYISAM
skip-innodb commented (with#)

Return on execution of your create statement:
Table creation OK!

Explanation: INNODB is active (skip-innodb commented) and it is used also if      
the default engine is MYISAM.

要重现测试,请在 my.cnf 中的每次更改后重新启动 MySql。

由于MySql 5.6版本的sqlmode默认不再为空,并且包含NO_ENGINE_SUBSTITUTION,而且INNODB是默认引擎,因此该错误很难满足。

其他测试

没有其他方法可以重现该错误:

Error Code: 1071. Specified key was too long; max key length is 1000 bytes 

在尝试创建INNODB表时发现。

在 INNODB 中,有两种 ERROR 1071:

Error Code: 1071. Specified key was too long; max key length is 767 bytes

这与 innodb_large_prefix ON 或 OFF 无关,而仅与用作索引的单个 VARCHAR 列的大小有关。

Mysql 存储 varchar utf8,其中 3 个字节加上 1 个字节,长度最多为 255 个字符,后面为 2 个字节(请参阅:http://dev.mysql.com/doc/refman/5.7/en/storage-requirements.html http://dev.mysql.com/doc/refman/5.7/en/storage-requirements.html),所以如果您尝试使用 VARCHAR(256) utf8 设置密钥,您会得到:

256 x 3 + 2 = 770 bytes

您会收到之前的错误,因为 InnoDB 表的单个列的最大键长度为 767 字节。 VARCHAR(255) 是可以的,因为:

255 x 3 + 1 = 766 bytes

我在四个版本的 Mysql(版本 5.1.56、5.5.33、5.6 和 5.7)上进行了测试,结果得到证实。使用 VARCHAR(255) 的查询没有问题,使用 VARCHAR(256) 的查询有问题:

Error Code: 1071. Specified key was too long; max key length is 767 bytes

正如你所看到的,消息是不同的,因为它是一条 INNODB 消息而不是 MYISAM 消息!

INNODB 表的 ERROR 1071 的另一种类型是:

Error Code: 1071. Specified key was too long; max key length is 3072 bytes

这与具有多列的键有关。要启用这些键,您需要将 innodb_large_prefix 设置为 on。 无论如何,如果你尝试运行这样的东西:

CREATE TABLE `phppos_modules_actions` (
  `action_id` VARCHAR( 255 ) CHARACTER SET utf8 COLLATE utf8_unicode_ci NOT NULL ,
  `module_id` VARCHAR( 255 ) CHARACTER SET utf8 COLLATE utf8_unicode_ci NOT NULL ,
  `action_name_key` VARCHAR( 255 ) CHARACTER SET utf8 COLLATE utf8_unicode_ci NOT NULL ,
  `action_name_key1` VARCHAR( 255 ) CHARACTER SET utf8 COLLATE utf8_unicode_ci NOT NULL ,
  `action_name_key2` VARCHAR( 255 ) CHARACTER SET utf8 COLLATE utf8_unicode_ci NOT NULL ,
  `sort` INT NOT NULL ,
  PRIMARY KEY ( `action_id` , `module_id`, `action_name_key`, `action_name_key1`, `action_name_key2` )
) ENGINE = INNODB CHARACTER SET utf8 COLLATE utf8_unicode_ci;

使用 5 个 VARCHAR(255) utf8 列(即 3830 字节)的键,您将遇到:

Error Code: 1071. Specified key was too long; max key length is 3072 bytes

奇异的假设

在寻找原因的过程中,我提出并测试了不同且相当奇怪的假设:

行格式

测试过 REDUNDANT、COMPACT、COMPRESS、DYNAMIC:对使用语句创建表没有影响。

文件格式

经过测试的羚羊和梭子鱼:对您的语句创建表没有影响。

MySql 搭建

测试了 32 位和 64 位 MySql:对使用语句创建表没有影响。

其他类似故障

在这里你可以发现相同情况下的相同错误:

https://www.drupal.org/node/2466287 https://www.drupal.org/node/2466287

我在 PROOF 中列出的 3 个测试情况中测试了该语句,它再现了与您完全相同的行为,所以我可以说问题是相同的。在这种情况下,他们切换到其他数据库,但问题是设置的混合,而不是数据库版本。

参考

这里给出了一篇关于 INNODB 索引的非常好的文章:

http://mechanics.flite.com/blog/2014/07/29/using-innodb-large-prefix-to-avoid-error-1071/ http://mechanics.flite.com/blog/2014/07/29/using-innodb-large-prefix-to-avoid-error-1071/

警告:在创建索引超过 1000 的 INNODB 表后,通过取消 my.cnf 中的skip-innodb 注释来禁用 INNODB 将不允许启动 MySql 服务

Regards

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

错误:指定的密钥太长;最大密钥长度为 1000 字节 的相关文章

  • 语言翻译语法

    我正在尝试为我的项目添加另一种语言 我们知道语言可以表现出主语和谓语的差异 例如 英语 Mustafa和他的朋友去看电影ahmet today 土耳其 Mustafa布昆 阿卡达西ahmetile birlikte sinemaya git
  • 导入 CSV 以更新表中的行

    大约有 26K 个产品 帖子 每个产品都有如下元值 post id 列是数据库中的产品 ID sku meta key 是每个产品的唯一 ID 我收到了一个新的 CSV 文件 该文件更新了每个产品的 sale price meta key
  • 解码Json数据数组并插入到mysql

    这个问题可能已经在这里问过 但我尝试搜索找不到它 我有如下 Json 数据 CityInfo CityCode 5599 Name DRUSKININKAI CityCode 2003 Name KAUNAS CityCode 2573 N
  • MySql如何通过过滤多列来限制多个数字?

    我想从数据库中获取 4 个不同类别的 50 个问题 我想要 4 个不同类别中每个类别的不同数量的问题 我的结果集必须包含第一类 12 个问题 第二类 20 个问题 第三类 10 个问题和第四类 8 个问题 我的问题表中总共有 50 个问题
  • 不唯一的表/别名

    因此 我尝试使用多个联接来运行此查询 以获得我想要的精确行 但我不断收到此错误 不唯一的表 别名 ss prices 我正在运行的查询 select ss accounts id ss accounts bot acc id ss acco
  • 使用 pip3 安装 mysqlclient 时遇到问题

    我正在尝试使用 Django 设置 python 3 6 环境 安装说明说我应该安装 mysqlclient 才能连接到 mySQL 我明白了 dennis django sudo H pip3 install mysqlclient Co
  • ER_ACCESS_DENIED_ERROR:用户 ''@'localhost' 的访问被拒绝(使用密码:NO)

    我有这个问题 我已经研究过但无法解决它 我想它与数据库权限有关 但我无法修复它 if error throw error Error ER ACCESS DENIED ERROR Access denied for user localho
  • 如何在 Laravel 中编写联合查询?

    我正在使用 laravel 5 0 并且我有 mysql 查询 SELECT surat masuk id surat surat masuk nomor surat FROM surat masuk WHERE EXISTS SELECT
  • 如何在MySQL中查找上周的数据

    我想显示来自 Q1 每个学生只有最后一周 Q2 每个学生只有最后一个月 我怎样才能实现这个目标 一周演示 http sqlfiddle com 2 f1fbb 3 当月演示 http sqlfiddle com 2 f1fbb 4 CREA
  • 使用 mysql2 gem 获取最后插入的 id

    我有这样的代码 require mysql2 db query insert into clients Name values client 我可以通过 1 个查询返回最后插入的 ID 吗 您可以使用last id客户端实例的方法 clie
  • MySql 查询在选择中将 NULL 替换为空字符串

    如何用空字符串替换 select 中的 NULL 值 输出 NULL 值看起来不太专业 这是非常不寻常的 根据我的语法 我希望它能够工作 我希望能得到一个解释 为什么没有 select CASE prereq WHEN prereq IS
  • ejabberd 16.06 + mysql 5.5.50,消息历史记录不保存

    我使用ejabberd 16 06 mysql 5 5 50 消息历史记录没有保存 我的 ejabberd yml MySQL server odbc type mysql odbc server freldo odbc port 3306
  • PDO::commit() 成功或失败

    The PHP PDO 提交 http www php net manual en pdo commit php文档指出该方法成功时返回 TRUE 失败时返回 FALSE 这是指beginTransaction 和commit 之间的语句执
  • 如何将 php Web 应用程序转换为桌面应用程序并保留数据库 [关闭]

    Closed 这个问题需要多问focused help closed questions 目前不接受答案 我们有一个用 PHP 开发的 Web 应用程序 但大多数客户并没有一直连接到互联网 那么 有没有办法将应用程序转换为桌面应用程序 以便
  • 使用MySQL计算单个表中借方和贷方的余额

    下面的 MySQL 表包含带有关联金额的借方或贷方 操作 如何选择具有非零 余额 的所有 CLIENT ID 我尝试将表连接到自身以计算所有借方和贷方总额 但有些东西无法正常工作 CLIENT ID ACTION TYPE ACTION A
  • 如何在 join 语句中进行计数

    我有桌子post int post id varchar title text content和表comment int comment id int post id varchar content其中 post id 是外键引用表帖子 如
  • Clojure MySQL 语法错误异常(“[...] 靠近 '???????????????' [...]”)

    除了建立连接之外 我在使用 clojure contrib sql 做任何事情时都遇到困难 我有一个 mysqld 在 localhost 3306 上运行 数据库名为clj db 用户 clj user localhost 和密码 clj
  • 如何使用 PHP 获取列中的所有值?

    我一直在到处寻找这个问题 但仍然找不到解决方案 如何从 mySQL 列中获取所有值并将它们存储在数组中 例如 表名称 客户 列名称 ID 名称 行数 5 我想获取此表中所有 5 个名称的数组 我该如何去做呢 我正在使用 PHP 我试图 SE
  • 哪个是识别关系或非识别关系中的子表?

    在表之间的识别和非识别关系的上下文中 MySQL 文档大量将表称为父表和子表 如何判断哪个表是父表 哪个表是子表 子表 A K A 弱实体 http en wikipedia org wiki Weak entity 是一个表 其主键属性d
  • SQL:查找每个跑步者跑步之间的平均天数

    因此 如果我们给出下表 runner ran Carol 2011 02 01 Alice 2011 02 01 Bob 2011 02 01 Carol 2011 02 02 Bob 2011 02 02 Bob 2011 02 03 B

随机推荐