"Mysql行大小太大"的更改限制

Las*_*urt 91 mysql

我该如何更改限制

行大小太大(> 8126).将某些列更改为TEXT或BLOB或使用ROW_FORMAT=DYNAMIC or ROW_FORMAT=COMPRESSED可能会有所帮助.在当前行格式中,BLOB内联存储768字节的前缀.

表:

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 
Run Code Online (Sandbox Code Playgroud)

hjp*_*r92 109

serverfault上也提出了这个问题.

您可能想看看这篇文章,它解释了很多关于MySQL行大小的内容.重要的是要注意,即使您使用TEXT或BLOB字段,您的行大小仍可能超过8K(InnoDB的限制),因为它为页面中的每个字段存储了前768个字节.

解决这个问题的最简单方法是在 InnoDB中使用Barracuda文件格式.这基本上只通过将20字节指针存储到文本数据而不是存储前768字节来完全解决问题.


适用于OP的方法有:

  1. 将以下内容添加到my.cnf文件下[mysqld].

    innodb_file_per_table=1
    innodb_file_format = Barracuda
    
    Run Code Online (Sandbox Code Playgroud)
  2. ALTER要使用的表ROW_FORMAT=COMPRESSED.

    ALTER TABLE nombre_tabla
        ENGINE=InnoDB
        ROW_FORMAT=COMPRESSED 
        KEY_BLOCK_SIZE=8;
    
    Run Code Online (Sandbox Code Playgroud)

上述内容仍有可能无法解决您的问题.这是InnoDB引擎的已知(并验证)错误,现在临时修复是作为临时存储回退到MyISAM引擎.所以,在你的文件中:my.cnf

internal_tmp_disk_storage_engine=MyISAM
Run Code Online (Sandbox Code Playgroud)

  • +1 - > innodb_file_per_table部分至关重要,与将格式更改为Barracuda密切相关.没有它,MySQL将默默地继续使用Antelope. (11认同)
  • 在我看来,这个答案与现代版本的 MySQL 无关。至少不是基于https://dba.stackexchange.com/a/125893/79826。 (3认同)
  • 使用`innodb_file_per_table = 1`激活此选项. (2认同)
  • 这不能保证解决问题.有关添加这些设置但仍能重现错误的示例脚本,请参阅[this post](https://bugs.mysql.com/bug.php?id=69336). (2认同)

Col*_*lin 59

我最近遇到了这个问题并以不同的方式解决了它.如果您运行的是MySQL版本5.6.20,则系统中存在已知错误.请参阅MySQL文档

重要由于Bug#69477,对于大型外部存储的BLOB字段的重做日志写入可能会覆盖最近的检查点.为解决此错误,MySQL 5.6.20中引入的补丁将重做日志BLOB写入的大小限制为重做日志文件大小的10%.作为此限制的结果,innodb_log_file_size应设置为大于表行中找到的最大BLOB数据大小的10倍以及其他可变长度字段(VARCHAR,VARBINARY和TEXT类型字段)的长度的值.

在我的情况下,令人讨厌的blob表约为16MB.因此,我解决它的方法是在my.cnf上添加一行,确保我至少有10倍的数量,然后是:

innodb_log_file_size = 256M


pho*_*nix 23

如果您可以切换ENGINE并使用MyISAM而不是InnoDB,那应该会有所帮助:

ENGINE=MyISAM

MyISAM有两个警告(可以说更多):

  1. 您不能使用交易.
  2. 您不能使用外键约束.

  • 如果您不介意没有事务和外键约束,那很好.但请注意,切换到MyISAM时会松开这些. (3认同)
  • 为我工作,ROW_FORMAT = DYNAMIC,谢谢! (2认同)
  • 这个建议太疯狂了——至少可以说是警告!事务和前键约束是这种格式中最少的问题! (2认同)
  • MyISAM 正在消失。 (2认同)
  • 为我工作。在我的案例中,我有 300 多个字段,每个字段的长度约为 10。我在这个表中没有任何关系,所以切换到 MyISAM 是解决办法。 (2认同)

Kar*_*arl 15

在my.cnf文件中设置以下内容并重启mysql服务器.

innodb_strict_mode = 0
Run Code Online (Sandbox Code Playgroud)

  • `innodb_strict_mode=0` -> 没有空格。否则,重新启动 mariaDB 10.2 会导致错误 :-P (2认同)
  • 根据文档,禁用严格模式只能防止出现错误和警告,因此它似乎并不能解决问题!http://download.nust.na/pub6/mysql/doc/innodb-plugin/1.1/en/innodb-other-changes-strict-mode.html (2认同)
  • 这似乎有效,让我可以毫无问题地创建表并存储数据 (2认同)

mul*_*axp 15

我遇到了同样的问题,这为我解决了:

ALTER TABLE `my_table` ROW_FORMAT=DYNAMIC;
Run Code Online (Sandbox Code Playgroud)

来自 MYSQL文档

DYNAMIC 行格式保持了在索引节点中存储整行(如果合适的话)的效率(就像 COMPACT 和 REDUNDANT 格式一样),但这种新格式避免了用大量数据字节填充 B 树节点的问题长列。DYNAMIC 格式基于这样的想法:如果长数据值的一部分存储在页外,通常将所有值存储在页外是最有效的。对于 DYNAMIC 格式,较短的列可能会保留在 B 树节点中,从而最大限度地减少任何给定行所需的溢出页数。


Ama*_*bra 12

我想分享一个很棒的答案,它可能会有所帮助.积分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格式.

基本要点:

  1. 一个16KB的InnoDB数据页面必须至少包含两行数据.此外,每个页面都有一个页眉和一个包含页面校验和和日志序列号的页脚,依此类推.这就是你的每行限制小于8KB的地方.

  2. 固定大小的数据类型(如INTEGER,DATE,FLOAT,CHAR)存储在此主数据页上,并计入行大小限制.

  3. 可变大小的数据类型(如VARCHAR,TEXT,BLOB)存储在溢出页面上,因此它们不会完全计入行大小限制.在Antelope中,除了存储在溢出页面上之外,在主数据页面上还存储多达768个字节的此类列.Barracuda支持动态行格式,因此它可能只在主数据页面上存储一个20字节的指针.

  4. 可变大小的数据类型也以1个或多个字节为前缀来编码长度.而InnoDB行格式也有一个字段偏移数组.因此,他们的wiki中或多或少都记录了内部结构.

Barracuda还支持ROW_FORMAT = COMPRESSED以进一步提高溢出数据的存储效率.

我还要评论说,我从未见过设计良好的表超过行大小限制.这是一种强烈的"代码味",你违反了第一范式的重复群体条件.


小智 7

花了几个小时后,我找到了解决方案:只需在 MySQL 管理员中运行以下 SQL 即可将表转换为 MyISAM:

USE db_name;
ALTER TABLE table_name ENGINE=MYISAM;
Run Code Online (Sandbox Code Playgroud)

  • `create table` 具有相同的选项:`CREATE TABLE ... ENGINE=MyISAM ...` (3认同)

U00*_*001 6

InnoDB 表的最大行大小(适用于数据库页中本地存储的数据)略小于半页(4KB、8KB、16KB 和 32KB)

\n\n

对于 16kb 页面(默认),我们可以计算:

\n\n
Slightly less than half a page 8126 / Number of bytes to threshold for overflow 767 = 10.59 fields of 767 bytes maximum\n
Run Code Online (Sandbox Code Playgroud)\n\n

基本上,你可以通过以下方式最大化一行:

\n\n
    \n
  • 11 个 varchar 字段 > 767 个字符(latin1 = 每个字符 1 个字节)或
  • \n
  • 11 个 varchar 字段 > 255 个字符(mysql 上的 utf-8 = 每个字符 3 个字节)。
  • \n
\n\n

请记住,如果该字段 > 767 字节,它只会溢出到溢出页。如果 767 字节的字段太多,它将崩溃(超出最大 row_size)。对于 latin1 来说不常见,但如果开发人员不小心\xe2\x80\x99 的话,对于 utf-8 来说很可能。

\n\n

对于这种情况,我认为您可以将 innodb_page_size 增加到 32kb。

\n\n

在 my.cnf 中:

\n\n
innodb_page_size=32K\n
Run Code Online (Sandbox Code Playgroud)\n\n

参考:

\n\n\n


Sou*_*rik 6

您需要对my.ini文件进行一些更改

在 [mysqld] 下添加此内容

innodb_strict_mode=0
Run Code Online (Sandbox Code Playgroud)

更新这两行

innodb_log_file_size=256M
innodb_log_buffer_size=256M
Run Code Online (Sandbox Code Playgroud)

innodb_strict_mode:启用后,某些 InnoDB 警告会变成错误。

参考: https: //mariadb.com/kb/en/innodb-strict-mode/

innodb_log_file_size&innodb_log_buffer_size需要增加尺寸。


Mih*_*ana 5

我在 AWS RDS 上使用 MySQL 5.6。我在参数组中更新了以下内容。

innodb_file_per_table=1
innodb_file_format = Barracuda
Run Code Online (Sandbox Code Playgroud)

我必须重新启动数据库实例才能使参数组更改生效。

此外,不支持 ROW_FORMAT=COMPRESSED。我使用如下 DYNAMIC ,效果很好。

ALTER TABLE nombre_tabla ENGINE=InnoDB ROW_FORMAT=DYNAMIC KEY_BLOCK_SIZE=8
Run Code Online (Sandbox Code Playgroud)