5.7到8.0版本升级导致备份导入失败:提示 "超过行长度"

5.7到8.0版本升级导致备份导入失败:提示 "超过行长度"

某应用开发商将用 mysqldump 从 MySQL5.7 导出的数据导入到GreatSQL时,某些表创建失败,提示超过行长度。

模拟信息如下

Java 复制代码
DROP TABLE cm_plat_user;
CREATE TABLE cm_plat_user
(id int NOT NULL AUTO_INCREMENT ,
netuserid varchar(255),
password varchar(255),
username varchar(255),
useaddress varchar(255),
mobilephone varchar(255),
telphone varchar(255) ,
email varchar(255) ,
sex   char(1) ,
user_type char(1),
description varchar(255),
userdespass varchar(255),
create_time datetime,
create_user varchar(255),
user_expire_time datetime,
passwd_expire_time datetime ,
login_flag char(1),
first_1ogintime datetime ,
last_logintime datetime DEFAULT NULL COMMENT '最后登录时间',
blocked_flag char(1),
blocked_reason  varchar(1000),
last_passwd_mod_time datetime,
user_status char(1),
home_url varchar(255),
theme varchar(255) ,
id_card_number varchar(255),
dept_name varchar(100),
admin_flag char(1) ,
area_code varchar(50) ,
PRIMARY KEY (id) ) ROW_FORMAT=COMPACT;

错误信息

error log信息

Shell 复制代码
2025-08-28T10:13:03.650086+08:00 34 [ERROR] [MY-011825] [InnoDB] Cannot add field blocked_reason in table demo.cm_plat_user because after adding it,
 the row size is 8761 which is greater than maximum allowed size (8126) for a record on index leaf page.

命令行终端报错信息

Bash 复制代码
ERROR 1118 (42000): 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.

问题分析

根据 error log 的日志信息表明,表 demo.cm_plat_user中添加字段 blocked_reason 后,行大小达到了 8761 字节,超过了 InnoDB 索引叶子页的最大允许大小 8126 字节。

问题反思

备份文件导入到GreatSQL时报错,导入MySQL 8.0.X会报错吗? 在MySQL 8.0.32(Server version: 8.0.32 MySQL Community Server - GPL)中进行测试,出现相同的报错信息。 MySQL 5.7升级到MySQL 8.0也有同样问题,说明该问题是MySQL 5.7和MySQL 8.0的差异导致的,版本升级的时候需要特别注意。

SQL 复制代码
mysql> select version();
+-----------+
| version() |
+-----------+
| 8.0.32    |
+-----------+
1 row in set (0.00 sec)
mysql> CREATE TABLE cm_plat_user
    -> (id int NOT NULL AUTO_INCREMENT ,
    -> netuserid varchar(255),
    -> password varchar(255),
    -> username varchar(255),
    -> useaddress varchar(255),
    -> mobilephone varchar(255),
    -> telphone varchar(255) ,
    -> email varchar(255) ,
    -> sex   char(1) ,
    -> user_type char(1),
    -> description varchar(255),
    -> userdespass varchar(255),
    -> create_time datetime,
    -> create_user varchar(255),
    -> user_expire_time datetime,
    -> passwd_expire_time datetime ,
    -> login_flag char(1),
    -> first_1ogintime datetime ,
    -> last_logintime datetime DEFAULT NULL COMMENT '最后登录时间',
    -> blocked_flag char(1),
    -> blocked_reason  varchar(1000),
    -> last_passwd_mod_time datetime,
    -> user_status char(1),
    -> home_url varchar(255),
    -> theme varchar(255) ,
    -> id_card_number varchar(255),
    -> dept_name varchar(100),
    -> admin_flag char(1) ,
    -> area_code varchar(50) ,
    -> PRIMARY KEY (id) ) ROW_FORMAT=COMPACT;
ERROR 1118 (42000): 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.

解决方案

1、根据命令行的报错提示,修改表行格式为 DYNAMIC 或 COMPRESSED,系统参数innodb_default_row_format默认值为dynamic,建表是去掉ROW_FORMAT=COMPACT后,创建的表行格式默认为dynamic。

2、修改页大小: 将 innodb_page_size 设置为 32KB 或更大,重新初始化数据库。

3、关闭严格检查模式:设置innodb_strict_mode=OFF,然后创建表

风险提示:关闭 innodb_strict_mode 仅为 "临时规避创建报错",并非根本解决方案。此时表虽能创建,但后续执行 INSERT/UPDATE 操作时,若实际数据仍导致行长度超限,会直接触发数据写入失败(报错 "Row size too large"),甚至可能因数据截断导致数据完整性问题。

使用建议:该方案仅适合 "紧急验证数据结构"场景,生产环境优先选择方案 1(修改行格式)或方案 2(调整页大小),避免长期关闭严格模式。

行格式说明

DYNAMIC和COMPACT的差异:

DYNAMIC 行格式会将 BLOB/TEXT 等大字段完全存储在溢出页中,行内只保留 20 字节的指针,COMPACT会在行内保留768 字节前缀。

DYNAMIC 行格式提供与 COMPACT 行格式相同的存储特性,但增加了针对长可变长度列的增强存储功能,并支持大索引键前缀。 当用 ROW_FORMAT=DYNAMIC`` 创建表时,InnoDB可以完全在页外存储长可变长度的列值(对于VARCHAR, VARBINARY, BLOB和TEXT类型),集群索引记录只包含一个指向溢出页的20字节指针。大于或等于768字节的固定长度字段被编码为可变长度字段。

使用COMPACT行格式的表将可变长度列值(VARCHAR、VARBINARY、BLOB和TEXT类型)的前768字节存储在B-tree节点内的索引记录中,其余的存储在溢出页上。大于或等于768字节的固定长度列被编码为可变长度列,可以存储在页外。

COMPRESSED压缩行格式提供与DYNAMIC行格式相同的存储特性和功能,但增加了对表和索引数据压缩的支持。

对于页外存储,COMPRESSED行格式使用了与DYNAMIC行格式类似的内部细节,同时对表和索引数据进行了额外的存储和性能考虑,并使用了更小的页面大小。对于COMPRESSED行格式,KEY_BLOCK_SIZE选项控制在聚集索引中存储多少列数据,以及在溢出页上放置多少列数据。

innodb_strict_mode参数说明

innodb_strict_mode=ON时,InnoDB在检查无效或不兼容的表选项时返回错误而不是警告。

它检查KEY_BLOCK_SIZE、ROW_FORMAT、DATA DIRECTORY、TEMPORARY和TABLESPACE选项是否相互兼容以及是否与其他设置兼容。

innodb_strict_mode=ON还在创建或修改表时启用行大小检查,以防止由于所选页面大小的记录太大而导致INSERT或UPDATE失败。

参考文章

dev.mysql.com/doc/refman/...

dev.mysql.com/doc/refman/...

相关推荐
小马爱打代码12 小时前
SpringBoot:封装 starter
java·spring boot·后端
STARSpace888812 小时前
SpringBoot 整合个推推送
java·spring boot·后端·消息推送·个推
Marktowin13 小时前
玩转 ZooKeeper
后端
蓝眸少年CY13 小时前
(第十二篇)spring cloud之Stream消息驱动
后端·spring·spring cloud
码界奇点13 小时前
基于SpringBoot+Vue的前后端分离外卖点单系统设计与实现
vue.js·spring boot·后端·spring·毕业设计·源代码管理
lindd91191114 小时前
4G模块应用,内网穿透,前端网页的制作第七讲(智能头盔数据上传至网页端)
前端·后端·零基础·rt-thread·实时操作系统·项目复刻
Loo国昌15 小时前
【LangChain1.0】第八阶段:文档处理工程(LangChain篇)
人工智能·后端·算法·语言模型·架构·langchain
vx_bisheyuange15 小时前
基于SpringBoot的海鲜市场系统
java·spring boot·后端·毕业设计
李慕婉学姐15 小时前
【开题答辩过程】以《基于Spring Boot和大数据的医院挂号系统的设计与实现》为例,不知道这个选题怎么做的,不知道这个选题怎么开题答辩的可以进来看看
大数据·spring boot·后端
源代码•宸16 小时前
Leetcode—3. 无重复字符的最长子串【中等】
经验分享·后端·算法·leetcode·面试·golang·string