改TEXT/BLOB能绕过8126字节限制,因InnoDB对这类字段采用页外存储:主记录页仅存20字节指针,实际内容存于溢出页;而VARCHAR(尤其COMPACT格式)需将全部内容塞入主页,导致页内非溢出部分超限。

为什么改TEXT/BLOB能绕过8126字节限制
因为InnoDB对TEXT和BLOB列的存储处理是“页外存储”:主记录页里只存20字节指针,实际内容放在独立的溢出页中。而VARCHAR(尤其在ROW_FORMAT=COMPACT下)会把全部内容(包括长值)尽量塞进主记录页,导致单行“可见体积”轻易突破8126字节上限——这个限制不是总行大小65535,而是**页内非溢出部分的最大承载量**。
哪些VARCHAR字段该立刻转TEXT/BLOB
别等报错才动,符合以下任一条件就该改:
-
VARCHAR定义长度 ≥ 5000,且实际写入内容常超1000字符(比如日志、HTML片段、JSON字符串) - 字段用于存Base64、富文本、序列化对象,不管当前长度多小,都建议用
LONGTEXT或JSON(MySQL 5.7+) - 表里已有≥2个大
VARCHAR,再加一个就大概率触发错误——这时别硬加,先评估是否真要放同一张表 - 字段带
DEFAULT长字符串(如DEFAULT '[]'对JSON字段还好,但DEFAULT '...500字符的模板文本...'会直接加重行开销)
ALTER TABLE时怎么安全改类型
直接MODIFY可能失败,尤其字段有索引或默认值。推荐分步操作:
面向 CRM 系统的 MySQL 8 数据库模式设计。当用户需要为客户关系管理(CRM)系统设计、评审、优化或生成数据库模式时,应使用此项技能。
- 先删掉该字段的
DEFAULT值:ALTER TABLE your_table ALTER COLUMN your_col DROP DEFAULT; - 再改类型:
ALTER TABLE your_table MODIFY your_col LONGTEXT;(TEXT适合≤64KB,超了用LONGTEXT) - 如果字段被索引,必须先
DROP INDEX,改完再重建——因为前缀索引对TEXT不生效,得确认业务是否真需要索引这个字段 - 改完执行
ANALYZE TABLE your_table;,避免优化器还按旧统计信息做执行计划
别忽略字符集和ROW_FORMAT的协同影响
同一个VARCHAR(1000)在utf8mb4下最多占4000字节,在latin1下只占1000字节。但即使你用了latin1,只要ROW_FORMAT还是COMPACT,多个大字段叠加照样撞上8126。所以:
- 改
TEXT/BLOB的同时,务必检查SHOW CREATE TABLE your_table;里有没有ROW_FORMAT=DYNAMIC - 没有就补上:
ALTER TABLE your_table ROW_FORMAT=DYNAMIC;(需确保innodb_file_per_table=ON,MySQL 5.6+默认开启) - 别依赖
innodb_strict_mode=0来掩盖问题——它只是让建表“成功”,插入真实数据时仍可能崩,且会让查询变慢、备份出错风险上升
真正卡住人的,往往不是单个大字段,而是多个“看起来还行”的VARCHAR叠在一起,再加上NULL标记位、索引前缀、字符集膨胀,最后在某个新增字段的瞬间彻底越界。动手前先SELECT SUM(CHAR_LENGTH(col)) FROM your_table LIMIT 1;粗估真实数据体积,比死盯DDL更管用。










