MySQL8建表VARCHAR总长未超65535却报行大小超限问题咨询
报错根因
你对VARCHAR长度和行上限的计算逻辑错了:MySQL规定的65535行长度上限是字节数限制,不是你以为的字符数限制。
- MySQL 8默认字符集是
utf8mb4,单个字符最多占用4字节,你定义的两个VARCHAR(10000)字段,单字段最大占用字节数是10000 * 4 = 40000,两个加起来就有80000字节,还没算其他字段的占用、以及长度超过255的VARCHAR需要额外2字节存储内容长度的开销,早就超过65535的硬限制了。 - 就算你手动指定用旧的
utf8mb3字符集(也就是老版本里误叫成utf8的字符集),单字符最多占3字节,两个VARCHAR(10000)最大也要占60000字节,再加上2个INT字段、2个DATETIME字段、VARCHAR长度标识的开销,一样会超阈值。
纠正你之前的认知偏差:TEXT类型性能弱于VARCHAR的结论只在特定场景成立。InnoDB在默认的DYNAMIC行格式下,长度较短的TEXT内容会直接存在数据页内,和VARCHAR的存储、查询逻辑没有本质区别,只有当内容长度超过行存储阈值时才会放到溢出页,这时候哪怕你定义的是VARCHAR类型,一样会走溢出页存储,拿不到你预期的性能收益。
可行方案
结合你99%场景字段长度小于255、仅极端情况更长的业务需求,选下面任意一种方案即可:
- 优先直接把两个字段改成
TEXT类型:完全绕开行长度限制,短内容的查询性能和VARCHAR没有可感知的差异,是改造成本最低、最匹配业务场景的方案。 - 如果坚持用VARCHAR类型,按你用的字符集下调字段定义的字符数上限:以utf8mb4为例,单表所有VARCHAR字段的总字符数不要超过16300(已经刨去了其他字段和额外开销的占用),比如把两个字段都设为
VARCHAR(8000)就可以正常建表。 - 没必要为了这个场景做表拆分、调整行格式这类过度设计,收益极低。
你可以先执行下面的语句确认当前库的默认字符集,自行核算VARCHAR的最大允许长度:
SELECT DEFAULT_CHARACTER_SET_NAME FROM information_schema.SCHEMATA WHERE SCHEMA_NAME = 'my-database';
内容的提问来源于stack exchange,提问作者gotali4396
相关产品推荐
相关产品推荐

