Mysql Row size too large (> 8126)

问题描述:Row size too large (> 8126). Changing some columns to TEXT or BLOB or using ROW_FORMAT=DYNAMIC or ROW_FORMAT=COMPRESSED may help. In current row format, BLOB prefix of 768 bytes is stored inline.

解决问题
有几种潜在的解决方案可以解决这个问题。

将表转换为动态行格式
如果表使用REDUNDANT或COMPACT行格式,则此问题的一种潜在解决方案是将表转换为使用DYNAMIC行格式。

如果您的表最初是在旧版本的 MariaDB 或 MySQL 上创建的,那么您的表可能使用 InnoDB 的旧行格式之一:

在MariaDB 10.1及之前版本以及 MySQL 5.6 及之前版本中,COMPACT行格式是默认行格式。
在 MySQL 4.1 及之前版本中,REDUNDANT行格式是默认行格式。
与这些旧的行格式相比,动态行格式可以在溢出页上存储更多的数据,因此这种行格式实际上可能能够安全地存储表的数据。有关更多信息,请参阅InnoDB 动态行格式:动态行格式的溢出页。

因此,行大小太大错误的潜在解决方案是将表转换为使用动态行格式。例如:

更改 表选项 卡 ROW_FORMAT = DYNAMIC ;
您可以使用information_schema数据库中的INNODB_SYS_TABLES表来查找使用REDUNDANT或COMPACT行格式的所有表。如果您希望将所有仍使用旧行格式的表转换为DYNAMIC行格式,这会很有帮助。例如,以下查询可以找到这些表,同时排除InnoDB 的内部系统表:

从信息架构中选择名称、 行格式
。innodb_sys_tables where row_format在('冗余' ,'compact' )中,并在(' sys_datafiles ' ,' sys_foreign','sys_foreign_cols' ,'sys_tablespaces' ,sys_tableSpaces' , sys_virtual', sys_virtual' ,sys_zip_dict' ,sys_zip_dict','sys_zip_c_cols_cols_ciccols'dict ;

在MariaDB 10.2及更高版本中,DYNAMIC行格式是默认行格式。如果您的表最初是在这些较新版本之一上创建的,那么它们可能已经在使用此行格式。在这种情况下,您可能需要尝试下一个解决方案。

在溢出页面上安装更多列
如果表已经使用DYNAMIC行格式,则此问题的另一个潜在解决方案是更改表架构,以便行格式可以在溢出页上存储更多列。

为了让 InnoDB 在溢出页上存储一些可变长度列,可能需要增加这些列的长度。

因此,很多情况下针对Row size Too Large错误的一个反直觉的解决方案实际上是增加一些变长列的长度,以便 InnoDB 的行格式可以将它们存储在溢出页上。

下面列出了更改表架构的一些可能方法。

将某些列转换为BLOBorTEXT
对于BLOB和TEXT列,动态行格式可以将这些列存储在溢出页上。有关更多信息,请参阅InnoDB 动态行格式:动态行格式的溢出页。

因此,行大小太大错误的潜在解决方案是将某些列转换为BLOB或TEXT数据类型。

VARBINARY增加列的长度
对于VARBINARY列,如果列的最大长度为 256 字节或更长,则DYNAMIC行格式只能将这些列存储在溢出页上。有关更多信息,请参阅InnoDB 动态行格式:动态行格式的溢出页。

因此,行大小太大错误的潜在解决方案是确保所有VARBINARY列至少与 一样长varbinary(256)。

VARCHAR增加列的长度
对于VARCHAR列,如果列的最大长度为 256 字节或更长,则DYNAMIC行格式只能将这些列存储在溢出页上。有关更多信息,请参阅InnoDB 动态行格式:动态行格式的溢出页。

本页前面显示的原始表架构会导致行大小太大错误,因为表的所有VARCHAR列都小于 256 字节,这意味着它们必须存储在行的主数据页上。

因此,行大小太大错误的一个潜在解决方案是确保所有VARCHAR列至少有 256 个字节长。达到 256 字节限制所需的字符数取决于列使用的字符集。

例如,当使用 InnoDB 的DYNAMIC行格式和默认字符集latin1(每个字符最多需要 1 个字节)时,256 字节限制意味着VARCHAR列只有在至少同样大的情况下才会存储在溢出页上作为一个varchar(256):
当使用 InnoDB 的DYNAMIC行格式和默认字符集utf8(每个字符最多需要 3 个字节)时,256 字节限制意味着VARCHAR列只有在至少与varchar(86):
当使用 InnoDB 的DYNAMIC行格式和默认字符集utf8mb4(每个字符最多需要 4 个字节)时,256 字节限制意味着VARCHAR列只有在至少与varchar(64):

解决问题
有几种方法可以解决这个问题。

如果您想要问题的解决方案而不仅仅是解决它,请参阅上一节中提到的解决方案。

将表重构为多个表
一个安全的解决方法是重构单个宽表,以便其列分布在多个表中。

如果您的表太宽以至于以前的解决方案无法解决表的问题,则此解决方法甚至可以发挥作用。

将一些列重构为 JSON
一种安全的解决方法是将某些列重构为 JSON 文档。

可以使用 MariaDB 的JSON 函数查询和操作 JSON 文档。

JSON 文档可以存储在使用以下数据类型之一的列中:

TEXT : TEXT列的最大大小为 64 KB。
MEDIUMTEXT : MEDIUMTEXT列的最大大小为 16 MB。
LONGTEXT : LONGTEXT列的最大大小为 4 GB。
JSON :这只是LONGTEXT数据类型的别名。
如果您的表太宽以至于以前的解决方案无法解决表的问题,则此解决方法甚至可以发挥作用。

禁用 InnoDB 严格模式
一个不安全的解决方法是禁用InnoDB 严格模式。可以通过将innodb_strict_mode系统变量设置为 来禁用InnoDB 严格模式。OFF

例如,即使以下表模式对于大多数 InnoDB 行格式来说太大而无法存储,但在禁用InnoDB 严格模式时仍然可以创建它:

但如上所述,如果禁用了InnoDB严格模式并且执行了DDL语句,那么 InnoDB 仍然会发出此消息的警告。SHOW WARNINGS语句可用于查看警告。例如:

如上所述,尽管 InnoDB 允许创建表,但仍然有可能出现错误。无论是否启用InnoDB 严格模式,如果执行的DML语句尝试写入表的 InnoDB 行格式无法存储的行,则 InnoDB 将引发错误并显示此消息。这会造成某种不安全的情况,因为这意味着应用程序在执行DML时有机会遇到其他错误。

原文链接:https://mariadb.com/kb/en/troubleshooting-row-size-too-large-errors-with-innodb/

posted @ 2024-01-19 17:33  张双健  阅读(1455)  评论(0编辑  收藏  举报