如何更改限制
行大小太大(> 8126)。将某些列更改为TEXT或BLOB或使用ROW_FORMAT=DYNAMIC or ROW_FORMAT=COMPRESSED
可能有所帮助。在当前行格式中,内联存储了{6}字节的BLOB
前缀。
表格
id int(11) No
name text No
date date No
time time No
schedule int(11) No
category int(11) No
top_a varchar(255) No
top_b varchar(255) No
top_c varchar(255) No
top_d varchar(255) No
top_e varchar(255) No
top_f varchar(255) No
top_g varchar(255) No
top_h varchar(255) No
top_i varchar(255) No
top_j varchar(255) No
top_title_a varchar(255) No
top_title_b varchar(255) No
top_title_c varchar(255) No
top_title_d varchar(255) No
top_title_e varchar(255) No
top_title_f varchar(255) No
top_title_g varchar(255) No
top_title_h varchar(255) No
top_title_i varchar(255) No
top_title_j varchar(255) No
top_desc_a text No
top_desc_b text No
top_desc_c text No
top_desc_d text No
top_desc_e text No
top_desc_f text No
top_desc_g text No
top_desc_h text No
top_desc_i text No
top_desc_j text No
status int(11) No
admin_id int(11) No
答案 0 :(得分:101)
此问题也在serverfault上提出。
您可能需要查看this article,其中解释了很多 关于MySQL行大小。重要的是要注意即使你使用 TEXT或BLOB字段,您的行大小仍可能超过8K(限制为 InnoDB)因为它为每个内联字段存储了前768个字节 页面。
解决此问题的最简单方法是使用Barracuda file format 与InnoDB。这基本上完全摆脱了这个问题 只存储20字节指针到文本数据而不是存储 前768个字节。
适用于OP的方法有:
将以下内容添加到my.cnf
部分下的[mysqld]
文件中。
innodb_file_per_table=1
innodb_file_format = Barracuda
ALTER
要使用的表格ROW_FORMAT=COMPRESSED
。
ALTER TABLE nombre_tabla
ENGINE=InnoDB
ROW_FORMAT=COMPRESSED
KEY_BLOCK_SIZE=8;
上述内容仍有可能无法解决您的问题。它是带有 InnoDB 引擎的known (and verified) bug,现在临时修复是作为临时存储回退到 MyISAM 引擎。所以,在my.cnf
文件中:
internal_tmp_disk_storage_engine=MyISAM
答案 1 :(得分:56)
我最近遇到了这个问题并以不同的方式解决了这个问题。如果您运行的是MySQL版本5.6.20,则系统中存在已知错误。见MySQL docs
重要 由于Bug#69477,对于大型外部存储的BLOB字段的重做日志写入可能会覆盖最多 最近的检查站。为解决这个问题,MySQL 5.6.20中引入的补丁限制了重做的大小 log BLOB写入重做日志文件大小的10%。由于此限制,innodb_log_file_size 应设置为大于您的行中找到的最大BLOB数据大小的10倍的值 表加上其他可变长度字段的长度(VARCHAR,VARBINARY和TEXT类型字段)。
在我的情况下,有问题的blob表大约是16MB。因此,我解决它的方法是在my.cnf上添加一行,确保我至少有10倍的数量,然后是一些:
innodb_log_file_size = 256M
答案 2 :(得分:22)
如果您可以切换ENGINE并使用MyISAM而不是InnoDB,那应该会有所帮助:
ENGINE=MyISAM
MyISAM有两个警告(可以说更多):
答案 3 :(得分:11)
我想分享一个很棒的答案,它可能会有所帮助。积分Bill Karwin在这里看到https://dba.stackexchange.com/questions/6598/innodb-create-table-error-row-size-too-large
它们因InnoDB文件格式而异。目前有2种格式称为Antelope和Barracuda。
中央表空间文件(ibdata1)始终采用Antelope格式。如果你使用file-per-table,你可以通过在my.cnf中设置innodb_file_format = Barracuda来使各个文件使用Barracuda格式。
基本要点:
InnoDB数据的一个16KB页面必须至少包含两行数据。此外,每个页面都有一个页眉和一个包含页面校验和和日志序列号的页脚,依此类推。这就是你的每行限制小于8KB的地方。
固定大小的数据类型(如INTEGER,DATE,FLOAT,CHAR)存储在此主数据页上,并计入行大小限制。
可变大小的数据类型(如VARCHAR,TEXT,BLOB)存储在溢出页面上,因此它们不会完全计入行大小限制。在Antelope中,除了存储在溢出页面上之外,在主数据页面上还存储多达768个字节的此类列。 Barracuda支持动态行格式,因此它可能只在主数据页面上存储一个20字节的指针。
可变大小的数据类型也以1个或多个字节为前缀来编码长度。而InnoDB行格式也有一个字段偏移数组。因此,他们的wiki中或多或少地记录了内部结构。
Barracuda还支持ROW_FORMAT = COMPRESSED以进一步提高溢出数据的存储效率。
我还要评论说,我从未见过设计良好的表超过行大小限制。这是一种强烈的“代码味”,你违反了第一范式的重复群体条件。
答案 4 :(得分:10)
在my.cnf文件中设置以下内容并重启mysql服务器。
innodb_strict_mode = 0
答案 5 :(得分:5)
花了几个小时后我找到了解决方案:只需在MySQL管理员中运行以下SQL将表转换为MyISAM:
package remoting
import akka.actor.{ActorSystem, Props}
import com.typesafe.config.ConfigFactory
object Main extends App {
val frontendConfig = ConfigFactory.load("frontend")
val frontend = ActorSystem("frontend", frontendConfig)
val frontendActor = frontend.actorOf(Props[FrontendActor], "FrontendActor")
(1 to 20).foreach(i => frontendActor ! f"Msg #$i")
frontendActor ! "stop"
}
答案 6 :(得分:2)
其他答案解决了问题。我将解决根本原因:架构设计不佳。
不要跨列显示数组。这里有3 * 10列,应该在新表格中加上10行3列(加id
等)
您的Main
表格只有
id int(11) No
name text No
date date No
time time No
schedule int(11) No
category int(11) No
status int(11) No
admin_id int(11) No
您的额外表格(Top
)会有
id int(11) No -- for joining to Main
seq TINYINT UNSIGNED -- containing 1..10
img varchar(255) No
title varchar(255) No
desc text No
PRIMARY KEY(id, seq) -- so you can easily find the 10 top_titles
每个Top
id
会有10行(或更少?或更多?)行。
这可以消除您的原始问题,并清除架构。 (这不是“正常化”,正如一些评论中所争论的那样。)
不切换到MyISAM;它会消失。
不要担心ROW_FORMAT
。
您需要更改代码才能执行JOIN
并处理多行而不是多列。
答案 7 :(得分:2)
我有同样的问题,这解决了我:
ALTER TABLE `my_table` ROW_FORMAT=DYNAMIC;
来自MYSQL Documentation:
DYNAMIC行格式保持整个存储的效率 索引节点中的行(如果它适合)(与COMPACT和REDUNDANT一样) 格式),但这种新格式避免了填充B树的问题 具有大量长列数据字节的节点。动态 格式基于如果长数据值的一部分是的概念 存储在页外,通常最有效的存储所有 超值的价值。使用DYNAMIC格式时,可能会使用较短的列 保留在B树节点中,最小化溢出页面的数量 任何给定的行都需要。
答案 8 :(得分:1)
当我尝试从其他服务器恢复备份的mysql数据库时,我遇到了这个问题。 为我解决这个问题的原因是在my.conf中添加了某些设置(如上面的问题)并另外更改了sql备份文件:
第1步: 在my.conf中添加或编辑以下行:
innodb_page_size=32K
innodb_file_format=Barracuda
innodb_file_per_table=1
步骤2 将ROW_FORMAT = DYNAMIC添加到导致此错误的表的sql备份文件中的表create语句中:
DROP TABLE IF EXISTS `problematic_table`;
/*!40101 SET @saved_cs_client = @@character_set_client */;
/*!40101 SET character_set_client = utf8 */;
CREATE TABLE `problematic_table` (
`id` bigint(20) NOT NULL AUTO_INCREMENT,
...
PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=3 ROW_FORMAT=DYNAMIC;
上面的重要更改是 ROW_FORMAT = DYNAMIC; (未包含在orignal sql备份文件中)
有助于我解决此问题的来源:MariaDB and InnoDB MySQL Row size too large
答案 9 :(得分:1)
InnoDB表的最大行大小适用于数据库页面中本地存储的数据,对于4KB,8KB,16KB和32KB,略小于一页的一半
对于16kb页面(默认),我们可以计算:
Slightly less than half a page 8126 / Number of bytes to threshold for overflow 767 = 10.59 fields of 767 bytes maximum
基本上,您可以通过以下方式最大化一行:
请记住,如果该字段大于767个字节,它将仅溢出到一个溢出页面。如果767个字节的字段太多,它将崩溃(超过最大row_size)。如果开发人员不小心,latin1并不常见,但是utf-8很有可能。
对于这种情况,我认为您可以将innodb_page_size增大到32kb。
在my.cnf中:
innodb_page_size=32K
参考文献:
答案 10 :(得分:0)
我也遇到了同样的问题。我通过执行以下sql来解决问题:
ALTER ${table} ROW_FORMAT=COMPRESSED;
但是,我想你应该知道Row Storage 有两种列:可变长度列(例如VARCHAR,VARBINARY和BLOB和TEXT类型)和固定长度列。它们存储在不同类型的页面中。
可变长度列是此规则的一个例外。诸如BLOB和VARCHAR之类的列太长而无法放在B树页面上的列存储在称为溢出页面的单独分配的磁盘页面上。我们将此类列称为页外列。这些列的值存储在单个链接的溢出页列表中,每个这样的列都有自己的一个或多个溢出页列表。在某些情况下,长列值的全部或前缀存储在B树中,以避免浪费存储并消除读取单独页面的需要。
当设置ROW_FORMAT的目的是
时的信息当使用ROW_FORMAT = DYNAMIC或ROW_FORMAT = COMPRESSED创建表时,InnoDB可以完全在页外存储长的可变长度列值(对于VARCHAR,VARBINARY,BLOB和TEXT类型),仅包含聚簇索引记录指向溢出页面的20字节指针。
答案 11 :(得分:0)
如果这种情况发生在具有许多列的SELECT上,则原因可能是mysql正在创建一个临时表。如果该表太大而无法容纳在内存中,它将使用其默认的临时表格式InnoDB将其存储在磁盘上。在这种情况下,将适用InnoDB大小限制。
然后您有4个选择:
将默认的临时表格式更改为MYISAM,这就是我所做的。 my.cnf中的更改:
internal_tmp_disk_storage_engine=MYISAM
重新启动mysql,查询正常。
答案 12 :(得分:0)
这是对任何有兴趣的人的简单提示:
使用10.3.17-MariaDB从Debian 9升级到Debian 10后,我在Joomla数据库中遇到一些错误:
[警告] InnoDB:无法在表field
中添加字段database
。table
,因为添加后,行大小为8742,该行大小大于允许的最大大小(8126)索引叶子页上的记录。
以防万一,我定了 innodb_default_row_format = /etc/mysql/mariadb.conf.d/50-server.cnf中的动态 (仍然是默认设置)
然后,我使用phpmyadmin为Joomla数据库中的所有表运行“优化表”。 我认为phpmyadmin在此过程中完成了表重新创建。 如果您碰巧安装了phpmyadmin,只需单击几下即可。
答案 13 :(得分:0)
我在AWS RDS上使用MySQL 5.6。我在参数组中更新了以下内容。
innodb_file_per_table=1
innodb_file_format = Barracuda
我必须重新引导数据库实例,以使参数组更改生效。
此外,不支持ROW_FORMAT = COMPRESSED。我按以下方式使用DYNAMIC,并且效果很好。
ALTER TABLE nombre_tabla ENGINE=InnoDB ROW_FORMAT=DYNAMIC KEY_BLOCK_SIZE=8
答案 14 :(得分:0)
您需要对my.ini
文件进行一些更改
在[mysqld]下添加它
innodb_strict_mode=0
更新这两行
innodb_log_file_size=256M
innodb_log_buffer_size=256M
innodb_strict_mode
:启用该选项后,某些InnoDB警告将变为错误。
参考:https://mariadb.com/kb/en/innodb-strict-mode/
innodb_log_file_size
和innodb_log_buffer_size
的大小需要增加。
答案 15 :(得分:0)
当我销毁Laravel Homestead(Vagrant)盒子并重新开始时,我一直遇到这个问题。
从命令行homestead ssh
转到my.cnf文件sudo vi /etc/mysql/my.cnf
将以下行添加到文件底部(在!includedir下方)
[mysqld]
innodb_log_file_size=512M
innodb_strict_mode=0
将更改保存到my.cnf,然后重新加载MYSQL sudo service mysql restart
答案 16 :(得分:0)
在 Mysql 5.6 上:
<块引用>执行以下 SQL 命令:
Mysql > SET GLOBAL innodb_file_format=Barracuda;
Mysql > ALTER TABLE `name_of_my_table_here` ENGINE=InnoDB ROW_FORMAT=DYNAMIC KEY_BLOCK_SIZE=8;