Navicat 17 保存表结构时报“Row size too large”说明其在客户端层主动校验InnoDB行宽,估算超65535字节即拦截;根本解决需将宽VARCHAR改为TEXT(主记录仅存20字节指针),并注意DEFAULT值、NOT NULL约束及统一utf8mb4字符集,>8126则须服务端执行ROW_FORMAT=DYNAMIC。
Navicat 17 保存表结构时直接报 Row size too large,说明什么
这不是 navicat 的 bug,而是它在保存前做了 innodb 行大小的静态校验——一旦估算出理论行宽(含字符集放大、隐藏字段、null 位图等)超过 65535 字节,就主动拦截并报错。此时表还没真正提交给 mysql,错误发生在客户端 ui 层,比服务端报错更早、更“友好”。
为什么改个 VARCHAR(65535) 就不行,但 TEXT 却可以
关键区别在存储机制:
-
VARCHAR内容全部存于主记录页内,长度声明即参与行宽计算(utf8mb4 下一个字符最多占 4 字节) -
TEXT/MEDIUMTEXT/LONGTEXT的实际内容存于溢出页,主记录只保留 20 字节指针,完全不计入65535行宽限制
所以当你在 Navicat 设计界面把类型从 VARCHAR 切成 TEXT,右侧“长度”输入框会自动变灰——这正是切换生效的信号。别手动填数字,也别试图拖动滑块绕过校验。
切 TEXT 后仍保存失败?检查这三个硬约束
常见卡点不是长度,而是字段定义冲突:
-
DEFAULT值非法:MySQL 5.7 不允许TEXT或LONGTEXT设字符串默认值,必须清空“默认值”栏 -
NOT NULL但没默认值:非空 TEXT 字段在 MySQL 中必须显式指定DEFAULT ''(或允许 NULL) - 字符集不一致:若表用
latin1,而你加了LONGTEXT字段,Navicat 可能静默失败;统一用utf8mb4最稳妥
为什么有时报 > 8126,有时报 > 65535
这两个数字指向不同层级的限制:
-
> 65535是 MySQL 层面的硬性行宽上限(所有引擎共用),含所有非 BLOB 字段的字节总和 -
> 8126是 InnoDB 特有的页内限制:当前ROW_FORMAT=COMPACT或REDUNDANT下,BLOB/TEXT 的前缀(默认 768 字节)被强制存入主记录页,这部分叠加其它字段后超了 8KB 的半页阈值
解决 > 8126 的最可靠方式是执行 ALTER TABLE your_table ROW_FORMAT=DYNAMIC;,让 BLOB/TEXT 完全外存,不再挤占主记录空间——这个操作必须在服务端执行,Navicat 设计界面改不了。
真正容易被忽略的是:即使你把所有大字段都换成了 TEXT,如果表里还有几十个 VARCHAR(255) 字段,加上 utf8mb4 编码和 NULL 位图,依然可能触达 65535 上限。这时候得回头删冗余字段,或者拆表——类型切换只是第一刀,不是万能解药。











