暂无图片
暂无图片
暂无图片
暂无图片
暂无图片

Mysql创建表报错ERROR 1118: Row size too large (> 8126)

原创 杨卓 2024-12-26
1814

问题现象

客户开发创建表时,报错
ERROR 1118: 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.

问题分析

MySQL创建字段的所有字段长度上限

innodb_strict_mode = on

innodb_strict_mode启用时, 在InnoDB检查无效或不兼容的表选项时返回错误而不是警告。
它检查 、KEY_BLOCK_SIZE、 ROW_FORMAT、DATA DIRECTORY和TEMPORARY选项 TABLESPACE是否相互兼容以及是否与其他设置兼容。
innodb_strict_mode=ON还可以在创建或更改表时启用行大小检查,以防止 INSERT或UPDATE由于记录对于所选页面大小来说太大而失败。
innodb_strict_mode您可以在启动时在命令行上mysqld或在 MySQL配置文件 中启用或禁用 。您还可以 innodb_strict_mode在运行时使用语句启用或禁用

InnoDB引擎限制

ROW_FORMAT=DYNAMIC

一个表最多可以包含 1017 列。虚拟生成的列包含在此限制中。
一个表最多可以包含 64 个 二级索引。
DYNAMIC行格式支持最多 3072 字节的索引键前缀 
多列索引最多允许 16 列。超出限制会返回错误。
对于 4KB、8KB、16KB 和 32KB 页面大小,最大行大小(不包括存储在页外的任何可变长度列)略小于页面的一半。例如,默认 innodb_page_size16KB 的最大行大小约为 8000 字节。但是,对于InnoDB 64KB 的页面大小,最大行大小约为 16000 字节。LONGBLOB和 LONGTEXT 列必须小于 4GB,并且包括列在内的总行大小BLOB必须 TEXT小于 4GB。
如果一行的长度小于半页,则所有行都存储在页面的本地。如果它超过半页,则选择可变长度列用于外部页外存储,直到该行适合半页。
尽管InnoDB内部支持大于 65,535 字节的行大小,但 MySQL 本身对所有列的组合大小施加了 65,535 的行大小限制。

通过阅读上述的官方文档,我们可以得知:
1.数据库表使用INNODB引擎;
2.数据库8.0,innodb_strict_mode 参数启用ON;
3.数据库行存储格式,使用ROW_FORMAT=DYNAMIC;
4.数据库使用默认大小,页innodb_page_size 16k时;
5.那么Mysql在创建表的时候,就会检测ALL字段的行长度,不能大于1/2 pages,就是8k;

问题复现

create table cc_test (
id varchar(32) not null,
fid varchar(12) default null,
val_1   text default null,
val_2   text default null,
......
val_200 text default null
primary key (id),
key index_fid (fid) using btree
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
ERROR 1118 (42000): 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.

方法一、网上大部分遇到的问题是varchar的字段加一起>8126,建议对varchar字段改成BLOB OR TEXT字段进行处理;
方法二、或者减少字段数量

模拟减少字段

省略,减少到196个text字段,创建成功,佐证了减少字段长度确实可以解决问题。

方法三、修改参数规避

innodb_strict_mode = off
会话层面修改:
mysql> create table cc_test (
    -> id varchar(32) not null,
    -> fid varchar(12) default null,
    -> val_1   text default null,
.......
    -> primary key (id)
    -> ) ENGINE=InnoDB DEFAULT CHARSET=utf8;
Query OK, 0 rows affected, 5 warnings (0.10 sec)

mysql> show warnings;
+---------+------+-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
| Level   | Code | Message                                                                                                                                                                     |
+---------+------+-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
| Warning | 1681 | Integer display width is deprecated and will be removed in a future release.                                                                                                |
| Warning | 1681 | Integer display width is deprecated and will be removed in a future release.                                                                                                |
| Warning | 1681 | Integer display width is deprecated and will be removed in a future release.                                                                                                |
| Warning | 3719 | 'utf8' is currently an alias for the character set UTF8MB3, but will be an alias for UTF8MB4 in a future release. Please consider using UTF8MB4 in order to be unambiguous. |
| Warning |  139 | 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.                                |
+---------+------+-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
5 rows in set (0.00 sec)

小结

1.虽然本次问题通过修改参数,临时规避了创建报错的问题;
2.但是Mysql启用check的目的是为了让表的查询、修改的效率得到提升,避免单行数据过大,但是本次的业务使用大量的text字段,里面存储的数据基本上是大于单行的长度,等于是可以存储数据,但是性能会很差;

参考
https://mysql.net.cn/doc/refman/8.0/en/innodb-parameters.html#sysvar_innodb_strict_mode
https://mysql.net.cn/doc/refman/8.0/en/innodb-row-format.html

「喜欢这篇文章,您的关注和赞赏是给作者最好的鼓励」
关注作者
【版权声明】本文为墨天轮用户原创内容,转载时必须标注文章的来源(墨天轮),文章链接,文章作者等基本信息,否则作者和墨天轮有权追究责任。如果您发现墨天轮中有涉嫌抄袭或者侵权的内容,欢迎发送邮件至:contact@modb.pro进行举报,并提供相关证据,一经查实,墨天轮将立刻删除相关内容。

评论