数据库

ERROR1118 的报错信息

2024-05-23

ERROR1118 的报错信息分为两种:

1. ERROR 1118 (42000): Row size too large. The maximum row size for the used table type, not counting BLOBs, is 65535. This includes storage overhead, check the manual. You have to change some columns to TEXT or BLOBs.

一行最大记录长度是 65535(定义到这个长度也会报错,行本身维护也会占用字节),建议使用 TEXT 或 BLOBs 类型。

2. Row size too large (> 8126). Changing some columns to TEXT or BLOB may help. In current row format, BLOB prefix of 0 bytes is stored inline.

一条记录太长,超过了 8126 字节,建议部分列使用 TEXT 或 BLOB 类型。

看到这两个报错信息,有些人可能就会有疑问,感觉描述的有些冲突,一个说一条记录最大长度不超过 65535 字节,一个说长度不能超过 8126 字节。那么到底哪个是正确的的呢?
先看下官方文档的描述:
https://dev.mysql.com/doc/refman/5.7/en/column-count-limit.html#row-size-limits

【The MySQL maximum row size limit of 65,535 bytes is demonstrated in the following InnoDB and MyISAM examples. The limit is enforced regardless of storage engine, even though the storage engine may be capable of supporting larger rows.】

在 MySQL 数据库中一条记录的最大长度是 65535 字节,在下面的 InnoDB 和 MyISAM 示例中做了演示。尽管存储引擎可能能够支持更大的行,但无论使用何种存储引擎,都会强制执行该限制。

【InnoDB restricts row size (for data stored locally within the database page) to slightly less than half a database page for 4KB, 8KB, 16KB, and 32KB innodb_page_size settings, and to slightly less than 16KB for 64KB pages.】

InnoDB 限制一条记录的大小(对于本地存储在数据库页面中的数据),对于 4KB、8KB、16KB 和 32KB 的 innodb_page_size 设置为略小于数据库页面的一半,对于 64KB 的页面则略小于 16KB。

小结:
一条记录最大长度 65535 字节是 MySQL 数据库 Server 层面的限制,默认情况下,InnoDB 页面大小是 16KB,所以 一条记录在页面中的存储长度不能超过 8126 字节,这是 InnoDB 存储引擎的限制。

这里可能会有些疑问,平常创建 varchar(10000) 类型字段,已经超过 8126 了,但也没报这个错误,这个和 InnoDB 的存储一条记录的格式有关系,官方文档对存储格式的说明:
https://dev.mysql.com/doc/refman/5.7/en/innodb-row-format.html#innodb-row-format-compact

【Fixed-length columns greater than or equal to 768 bytes are encoded as variable-length columns, which can be stored off-page】

当列的长度超过 768 字节时,多余的内容会存储到一个溢出页上,compact/dynamic 格式在这方面是一样的。
也就是说创建了 varhcar(10000) 类型字段,同时写入到 10000 字节的数据,其实只有 768 个字节存储在数据页面上,其余的字节存储在溢出页面上。

为什么Innodb存储引擎,每个存储页面上,最少要有两条记录呢?

截图来自于【MySQL运维内参】

mysql数据库表.png

这是假如每个页面只能存储一条记录的情况下,表内存储了【1,2,3,4】4 条记录 B+ 树结构图,如果一个页面的数据量不能存储 2 条记录,则这个 B+ 树就不能称为 B+ 树,因为它起不到一个索引的作用,其实就是一个双向链表,但比双向链表占用的空间大很多。
如果不能够存储 2 条记录,那么这个 B+ 树是没有意义的,形不成一个有效的索引。

总结:
创建表和写入数据时有两个限制,一个是 Server 层面的限制,一条记录最大长度不能超过 65535(真实创建的记录长度到不了 65535,因为记录本身也需要一些字节去维护),另一个是 InnoDB 层面的限制,一条记录存储在页面中的长度不能够超过 8126 字节。