Mysql的问题 Row size too large (> 8126).

文章目录

  • Mysql的问题 Row size too large (> 8126).
    • COMPACT Row Format
      • COMPACT 行格式存储特性
    • DYNAMIC Row Format
      • 动态行格式存储特性
      • 什么是off-page
      • overflow page
      • off-page column
    • 两种行格式的区别
    • 解法方法
    • 参考文章

最近项目中 存储数据 遇到了一个问题, 我在更新一张表的时候 报了一个错误,错误如下:

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.

根据提示 需要修改了 ROW_FORMAT 格式, row size 太大了, 超过了mysql 的page size 限制.

首先我更新这个表有40多个 字段,很多字段都是varchar 类型,还有一些text 类型

目前环境中使用的数据库 还是比较旧的, mysql 版本为: 5.6.20 ,从报错的日志来看就是一行数据太多了,超过了mysql 行的大小限制。查看mysql的文档里面有提及 5.6 column count limit

查看了一下表结构

这个表的引擎 使用Innodb , row_format使用的是 COMPACT

CREATE TABLE `xxxxx_table_name` (`id` bigint(20) NOT NULL AUTO_INCREMENT,`create_date` timestamp NULL DEFAULT CURRENT_TIMESTAMP,`update_date` timestamp NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,... // 此处省略 ...PRIMARY KEY (`id`)) ENGINE=InnoDB DEFAULT CHARSET=utf8 ROW_FORMAT=COMPACT;

读一下mysql 的文档 5.6 column count limit

  • 首先 MySQL 表 自身有一个限制 65535字节 最大行大小限制,即使存储引擎是能够支持的更大的行。

  • BLOB并且 TEXT列仅对行大小限制贡献 9 到 12 个字节,因为它们的内容与行 的其余部分分开存储。

  • 对于使用 InnoDB 的数据表,最大行略小于 半页(half a page)。 对于默认的配置 InnoDB 页大小为16kb , 所以最大行略小于8kb , 这个是由于 innodb_page_size 配置定义的。

  • 如果包含 可变长度列的InnoDB 行超过最大行大小,InnoDB则为外部页外存储选择可变长度列,直到该行适合InnoDB 行大小限制。对于页外存储的可变长度列,本地存储的数据量因行格式而异。有关更多信息,请参阅 第 14.11 节,“InnoDB 行格式”。

  • 不同的存储格式使用不同数量的页头和尾部数据,这会影响行可用的存储量。

    • 有关InnoDB行格式的信息,请参阅第 14.11 节,“InnoDB 行格式”。
    • 有关MyISAM 存储格式的信息,请参阅 第 15.2.3 节,“MyISAM 表存储格式”。

我们这里只需要 先看 InnoDB 行格式 即可, row size 取决于 底层数据是如何存储的。 这里我只看 InnoDB 引擎的表。

InnoDB存储引擎支持四名的格式REDUNDANTCOMPACTDYNAMIC,和COMPRESSED

Table 14.7 InnoDB Row Format Overview

Row Format Compact Storage Characteristics Enhanced Variable-Length Column Storage Large Index Key Prefix Support Compression Support Supported Tablespace Types Required File Format
REDUNDANT No No No No system, file-per-table Antelope or Barracuda
COMPACT Yes No No No system, file-per-table Antelope or Barracuda
DYNAMIC Yes Yes Yes No file-per-table Barracuda
COMPRESSED Yes Yes Yes Yes file-per-table Barracuda

好了,现在我们用的是 COMPACT 这种Row Format 这种所需要的文件格式 有两种 Antelope or Barracuda

COMPACT row format 我不太知道如何翻译, 紧凑的行格式,暂且叫这个名字吧。

COMPACT Row Format

COMPACT 行格式

  • 这个格式的好处,是对行格式进行了压缩 对比 REDUNDANT 这个格式 会减少约20% 的空间。

  • COMPACT行的格式是由两个支持 InnoDB的文件格式(AntelopeBarracuda

  • 使用COMPACT行格式的表将前 768 个字节的可变长度列值(VARCHARVARBINARYBLOBTEXT类型)存储在B 树节点内的索引记录中,其余部分存储在溢出页上。大于或等于 768 字节固定长度列被编码为可变长度列,可以在页外存储 (off-page)。例如, CHAR(255)如果字符集的最大字节长度大于 3,则列可以超过 768 个字节,就像使用utf8mb4.

  • 如果列的值是 768 字节或更少,则不使用溢出页(overflow page),并且可能会节省一些 I/O,因为该值完全存储在 B 树节点中。这适用于相对较短的BLOB列值,但可能会导致 B 树节点填充数据而不是键值,从而降低其效率。具有许多BLOB列的表可能会导致 B 树节点变得太满,并且包含的行太少,从而使整个索引的效率低于行较短或列值存储在页外的情况。

COMPACT 行格式存储特性

COMPACT行格式有如下存储特性:

  • 每个索引记录都包含一个 5 字节的标头,该标头前面可能有一个可变长度的标头。标头用于将连续记录链接在一起,并用于行级锁定。

  • 记录头的可变长度部分包含用于指示NULL列的位向量。如果索引中的列数可以 NULL是*N*,则位向量占 N/8 字节。(例如,如果有 9 到 16 列可以是,则位向量使用两个字节。) 列不占用此向量中的位以外的空间。标题的可变长度部分还包含可变长度列的长度。每个长度需要一个或两个字节,具体取决于列的最大长度。如果索引中的所有列都是NOT NULL 并且有固定长度,记录头没有变长部分。

  • 对于每个非NULL可变长度字段,记录头包含一或两个字节的列长度。仅当部分列外部存储在溢出页中或最大长度超过 255 字节且实际长度超过 127 字节时才需要两个字节。对于外部存储的列,2 字节长度表示内部存储部分的长度加上指向外部存储部分的 20 字节指针。内部部分是768字节,所以长度是768+20。20 字节的指针存储列的真实长度。

  • 记录头(The record header) 后面是非NULL列的数据内容。

  • 聚集索引中的记录包含所有用户定义列的字段。此外,还有一个 6 字节的**事务 ID 字段(transaction ID field )和一个 7 字节的滚动指针(roll pointer)**字段。

  • 如果没有为表定义主键,则每个聚集索引记录还包含一个 6 字节的 row ID 字段。

  • 每个二级索引记录包含为聚集索引键定义的所有不在二级索引中的主键列。如果任何主键列是可变长度的,则每个二级索引的记录头都有一个可变长度部分来记录它们的长度,即使二级索引是在固定长度的列上定义的。

  • 在内部,对于非可变长度字符集,诸如固定长度字符列 CHAR(10)以固定长度格式存储。

    尾随空格不会从VARCHAR列中截断 。

  • 在内部,对于诸如utf8mb3 and utf8mb4 之类的可变长度字符集, InnoDB尝试通过修剪尾随空格 以字节形式存储 。如果 列值的字节长度 超过N 字节,则尾随空格将被修剪为列值字节长度的最小值。 CHAR(N)列的最大长度为 最大字符字节长度 × N

    为CHAR(N)保留了最小的N个字节。在很多情况下,保留最小的空间N 可以使列的更新在原地进行,而不会造成索引页的碎片化。相比之下,当使用REDUNDANT行格式时,CHAR(N)列占用的最大字符字节长度×N。

    大于或等于 768 字节的固定长度列被编码为可变长度字段,可以在**页外(off-page)**存储。例如,CHAR(255)如果字符集的最大字节长度大于 3,则列可以超过 768 个字节,就像使用 utf8mb4.

The COMPACT row format has the following storage characteristics:

  • Each index record contains a 5-byte header that may be preceded by a variable-length header. The header is used to link together consecutive records, and for row-level locking.

  • The variable-length part of the record header contains a bit vector for indicating NULL columns. If the number of columns in the index that can be NULL is N, the bit vector occupies CEILING(N/8) bytes. (For example, if there are anywhere from 9 to 16 columns that can be NULL, the bit vector uses two bytes.) Columns that are NULL do not occupy space other than the bit in this vector. The variable-length part of the header also contains the lengths of variable-length columns. Each length takes one or two bytes, depending on the maximum length of the column. If all columns in the index are NOT NULL and have a fixed length, the record header has no variable-length part.

  • For each non-NULL variable-length field, the record header contains the length of the column in one or two bytes. Two bytes are only needed if part of the column is stored externally in overflow pages or the maximum length exceeds 255 bytes and the actual length exceeds 127 bytes. For an externally stored column, the 2-byte length indicates the length of the internally stored part plus the 20-byte pointer to the externally stored part. The internal part is 768 bytes, so the length is 768+20. The 20-byte pointer stores the true length of the column.

  • The record header is followed by the data contents of non-NULL columns.

  • Records in the clustered index contain fields for all user-defined columns. In addition, there is a 6-byte transaction ID field and a 7-byte roll pointer field.

  • If no primary key is defined for a table, each clustered index record also contains a 6-byte row ID field.

  • Each secondary index record contains all the primary key columns defined for the clustered index key that are not in the secondary index. If any of the primary key columns are variable length, the record header for each secondary index has a variable-length part to record their lengths, even if the secondary index is defined on fixed-length columns.

  • Internally, for nonvariable-length character sets, fixed-length character columns such as CHAR(10) are stored in a fixed-length format.

    Trailing spaces are not truncated from VARCHAR columns.

  • Internally, for variable-length character sets such as utf8mb3 and utf8mb4, InnoDB attempts to store CHAR(*N*) in N bytes by trimming trailing spaces. If the byte length of a CHAR(*N*) column value exceeds N bytes, trailing spaces are trimmed to a minimum of the column value byte length. The maximum length of a CHAR(*N*) column is the maximum character byte length × N.

    A minimum of N bytes is reserved for CHAR(*N*). Reserving the minimum space N in many cases enables column updates to be done in place without causing index page fragmentation. By comparison, CHAR(*N*) columns occupy the maximum character byte length × N when using the REDUNDANT row format.

    Fixed-length columns greater than or equal to 768 bytes are encoded as variable-length fields, which can be stored off-page. For example, a CHAR(255) column can exceed 768 bytes if the maximum byte length of the character set is greater than 3, as it is with utf8mb4.

DYNAMIC Row Format

动态行格式

  • DYNAMIC行格式提供相同的存储特性的COMPACT行格式,但增加了增强的长的可变长度列和支持大型索引键前缀的存储能力。

  • DYNAMIC行格式被支持的 Barracuda文件格式, 要创建使用DYNAMIC行格式的表,innodb_file_format必须将该 变量设置为Barracuda,并且innodb_file_per_table必须启用该 变量。

  • 当创建一个ROW_FORMAT=DYNAMIC的表时,InnoDB可以将长的可变长度的列值(对于VARCHAR,VARBINARY,以及BLOB和TEXT类型)完全放在页外(off-page),聚类索引记录只包含一个20字节的指向溢出页的指针。对于 大于或等于768字节的固定长度字段被编码为可变长度字段。例如,如果字符集的最大字节长度大于3,一个CHAR(255)列可以超过768字节,正如utf8mb4那样。

  • 列是否存储在页外取决于页面大小(page size)和行的总大小。当一行太长时,选择最长的列进行页外存储,直到聚集索引记录适合B 树 页面(page)。 TEXT并且 BLOB小于或等于 40 字节的列存储在行中。

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

  • DYNAMIC行格式支持索引键的前缀,最大可达3072字节。这个功能是由innodb_large_prefix变量控制的,默认情况下是禁用的。更多信息请参见innodb_large_prefix` 变量描述。

The DYNAMIC row format offers the same storage characteristics as the COMPACT row format but adds enhanced storage capabilities for long variable-length columns and supports large index key prefixes.

The DYNAMIC row format is supported by the Barracuda file format. For more information, see Section 14.10, “InnoDB File-Format Management”. To create tables that use the DYNAMIC row format, the innodb_file_format variable must be set to Barracuda, and the innodb_file_per_table variable must be enabled.

When a table is created with ROW_FORMAT=DYNAMIC, InnoDB can store long variable-length column values (for VARCHAR, VARBINARY, and BLOB and TEXT types) fully off-page, with the clustered index record containing only a 20-byte pointer to the overflow page. Fixed-length fields greater than or equal to 768 bytes are encoded as variable-length fields. For example, a CHAR(255) column can exceed 768 bytes if the maximum byte length of the character set is greater than 3, as it is with utf8mb4.

Whether columns are stored off-page depends on the page size and the total size of the row. When a row is too long, the longest columns are chosen for off-page storage until the clustered index record fits on the B-tree page. TEXT and BLOB columns that are less than or equal to 40 bytes are stored in line.

The DYNAMIC row format maintains the efficiency of storing the entire row in the index node if it fits (as do the COMPACT and REDUNDANT formats), but the DYNAMIC row format avoids the problem of filling B-tree nodes with a large number of data bytes of long columns. The DYNAMIC row format is based on the idea that if a portion of a long data value is stored off-page, it is usually most efficient to store the entire value off-page. With DYNAMIC format, shorter columns are likely to remain in the B-tree node, minimizing the number of overflow pages required for a given row.

The DYNAMIC row format supports index key prefixes up to 3072 bytes. This feature is controlled by the innodb_large_prefix variable, which is disabled by default. See the innodb_large_prefix variable description for more information.

动态行格式存储特性

DYNAMIC行格式是COMPACT行格式的一个变种。关于存储特性,见COMPACT行格式存储特性。

什么是off-page

MySQL的表中存储数据的时候,数据是一行一行的存储的。这个行要落在innodb的最小存储单位:page页中。好比我们的书本中的一行一行的文字是在页中,一个页里面有很多行。MySQL中的page页,就是用来存储多个行的基本单位。

但是如果一个行特别的大,大于了16KB的大小,那么此时一个page页,就容纳不下这个行了,此时就要在用2个甚至更多的page页来存储这个行的数据,这种现象就是off-page,即行溢出,off-page是指一个表的单行的大小超过了MySQL默认的一个page页的大小。一个行,要占用多个页来存储对于这种现象,在不同的行存储格式下面会有不同的处理方式,下面会有详细的介绍。默认的方式是将多余的数据需要在overflow-page溢出页中存储。
————————————————
版权声明:本文为CSDN博主「程序猿集锦」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/javaanddonet/article/details/111992640

overflow page

Separately allocated disk pages that hold variable-length columns (such as BLOB and VARCHAR) that are too long to fit on a B-tree page. The associated columns are known as off-page columns.

溢出页
单独分配的磁盘页,用于存放可变长度的列(如BLOB和VARCHAR),这些列太长了,不能放在B树页上。相关的列被称为页外列。

off-page column

A column containing variable-length data (such as BLOB and VARCHAR) that is too long to fit on a B-tree page. The data is stored in overflow pages. The DYNAMIC row format is more efficient for such storage than the older COMPACT row format.

页外列
一个包含可变长度数据(如BLOB和VARCHAR)的列,它太长了,不能放在B树的页面上。这些数据被存储在溢出页中。DYNAMIC行格式比老的COMPACT行格式对这种存储更有效。

两种行格式的区别

通过对比发现这两种格式一个显著的区别

对于COMPACT Row Format 这种格式 会把可变长度类型(VARCHAR,BLOB,TEXT,VARBINARY) 会将前768个字节存储在B-tree 的索引记录中. 超出的部分会存储在 溢出页上( overflow pages). 大于或等于 768 字节的固定长度列被编码为可变长度列,可以在页外存储 (off-page)

DYNAMIC Row Format 这种格式的特点 增强的长的可变长度列和支持大型索引键前缀的存储能力。

这中格式会把(VARCHAR,BLOB,TEXT,VARBINARY类型)完全放在页外(off-page) , 对于大于768 字节的固定长度列,会自动编码会可变长度列。

解法方法

回到一开始的问题 Row size too large

说明我的可变类型的字段太多了, 并且都比较长, 然后超过 8126个字节,无法满足我的需要。

所以我可以使用 改变 row format 来 把这些可变类型存储到off-page.

mysql> SET GLOBAL innodb_file_per_table = ON;
mysql> SET GLOBAL innodb_file_format = Barracuda;

改完之后需要 查看一下是否已经修改成功.

show  variables like '%innodb_file_format%'; show  variables like 'innodb_file_per_table%';

对之前的表进行修改

ALTER TABLE `xxxxx_table_name` ROW_FORMAT=DYNAMIC;

或者创建一个新表结构 只需要 指定一下 row_format

CREATE TABLE `xxxxx_table_name` (`id` bigint(20) NOT NULL AUTO_INCREMENT,`create_date` timestamp NULL DEFAULT CURRENT_TIMESTAMP,`update_date` timestamp NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,... // 此处省略 ...PRIMARY KEY (`id`)) ENGINE=InnoDB DEFAULT CHARSET=utf8 ROW_FORMAT=DYNAMIC;

查看表的基本的信息

-- 查看建表语句
show  create table  table_name;-- Determining the Row Format of a Table
-- 查看表的engine 信息, row_format 信息, table size ,index length , data length 等等.
SHOW TABLE STATUS like 'table_name' ;-- 或者 使用
SHOW TABLE STATUS IN table_name;

参考文章

stackoverflow row size too large

innodb_file_format配置

column count limit

innodb row format

char 类型存储特点:11.3.2 The CHAR and VARCHAR Types

什么是off-page

glos_off_page_column

分享快乐,留住感动. '2021-12-20 20:59:10' --frank

Mysql的问题 Row size too large相关推荐

  1. 【MySQL异常】Row size too large (> 1982). Changing some columns to TEXT or BLOB or using ROW_FORMAT=DYNA

    本文目录 一.背景描述 二.报错内容 三.解决方案 四.拓展 一.背景描述 MySQL版本:5.6.28, MySQL引擎 InnoDB.本地环境.开发环境.生产环境数据库版本一模一样. 昨天晚上更新 ...

  2. mysql报错 Row size too large ( 8126)

    报错信息 Row size too large (> 8126). Changing some columns to TEXT or BLOB or using ROW_FORMAT=DYNAM ...

  3. mysql1118,mysql5.7 [Err] 1118 - Row size too large ( 8126). | 航行学园

    mysql [Err] 1118 - Row size too large (> 8126). 问题 mysql5.7 在执行创建表或者增加字段时,发现row size长度过长,导致出现以下错误 ...

  4. mysql err 1118_MySQL ERROR1118报错详解 Row size too large

    ERROR1118的报错信息分为两种: 1.ERROR 1118 (42000): Row size too large. The maximum row size for the used tabl ...

  5. mysql data too large_MySQL数据库之mysql 主从同步故障解决   Error 'Row size too large ( 8126)....

    本文主要向大家介绍了MySQL数据库之mysql 主从同步故障解决   Error 'Row size too large (> 8126). ,通过具体的内容向大家展现,希望对大家学习MySQ ...

  6. mysql:Row size too large (> 8126)

    这个错误简单理解就是单行记录的合计最大大小超过了8126字节,那么根据文档描述的话,使用dynamic行格式的表行最大大小可以达到65536字节(因为mysql内部使用了2个字节来表示字段长度,因此可 ...

  7. MySQL - Row size too large (> 8126). Changing some columns to TEXT or BLOB

    报错信息 Row size too large (> 8126). Changing some columns to TEXT or BLOB 分析原因 因为 mysql 默认的 page 最大 ...

  8. Mysql数据库报错:Row size too large (> 8126). Changing some columns to TEXT or BLOB or using ROW_FORMAT=DY

    1.问题描述: Row size too large (> 8126). Changing some columns to TEXT or BLOB or using ROW_FORMAT=DY ...

  9. Mysql数据库报错:Row size too large ( 8126). Changing some columns to TEXT or BLOB or using ROW_FORMAT=DY

    1.问题描述: Row size too large (> 8126). Changing some columns to TEXT or BLOB or using ROW_FORMAT=DY ...

最新文章

  1. 很实用的 “设为首页”与“加入收藏”代码
  2. 5.1 tushare包介绍
  3. Python使用exec自动生成代码并执行,同时得到返回的变量
  4. c语言sort函数排序二维数组,关于C++ 的 sort 对二维数组排序。该如何解决
  5. Android 5.0+(RecycleView、CardView、Palette)
  6. iofactory.php,CI框架下引入类库资源PHPPowerPoint报出“ Cannot redeclare class IOFactory”...
  7. ftp协议是一种用于什么的协议_购房协议怎么写?签购房协议要注意什么
  8. 武汉理工大学计算机专业课程表,武汉理工大学2014年春季第一周课表.xls
  9. Mac 卸载Symantec软件
  10. Java文字转图片超出内容自动换行
  11. nginx正向代理反向代理负载均衡
  12. 结合运动流的时间先验在微创手术视频中的器械分割
  13. 福州市建筑物矢量数据(Shp格式+带高度)
  14. hexo的next主题换到Yelee(Yilia)
  15. k-means算法及python实现
  16. Rigidbody.AddForce 添加力
  17. 永久可用的代理IP和推广佣金的游戏
  18. 完善发现、培养、激励机制 全面增强科技人才活力|方格教育
  19. 关于html页面转为 jsp页面中文乱码问题
  20. Something I'll Referrence

热门文章

  1. 第21节--非线性回归(下)
  2. IDEA springboot 项目启动报错 Shorten the command line via JAR manifest or via a classpath file and rerun
  3. switch函数用法与错误分析
  4. EasyAR涂涂乐代码分析
  5. AR涂涂乐⭐二、 给material赋予材质、移除material、调整扫描框透明度
  6. nginx php多域名配置文件,配置文件,nginx_nginx多站点配置,无法通过域名访问,使用ip访问会跳转到其中一个站点,配置文件,nginx - phpStudy...
  7. 计算机死机后 通过任务管理器关闭程序,电脑死机后,按哪个键结束程序
  8. 【C语言练习——打印杨辉三角及其变形】
  9. 怎么用python生成带二维码的照片_怎么制作二维码图片-Python 生成个性二维码
  10. 电脑端扫描二维码(java)