2¹² = 4096 列
程序里用 12 个 bit 来存「列的编号」(MySQL Server层的限制)
区分65535:MySQL Server行缓冲区结构用16位无符号整数标记行总长度,最大值65535字节
额外约束
一定能有4096列吗?
情况1:InnoDB引擎额外约束
4096只是MySQL服务层的限制,InnoDB额外加了个更严格的上限:1017 列
MyISAM仍能接近 4096(可以等于但很难,看下面就知道了),InnoDB可到达1017,高了报错
情况2:如果是MyISAM能到4096/1017吗
限制重申:
- Server:单行非大字段总长度 ≤ 65535 字节 (
2^16-1) - Server:列数量上限 4096
- InnoDB:实际列上限 1017(这个是硬坎,生产都是 InnoDB,所以我们暂按 1017 列去算)
想要到达1017=>65535 ÷ 1017 ≈ 64.44 字节 / 列
本次模拟计算忽略了TEXT/BLOB
TEXT:存字符串文本(有字符集),分 TINYTEXT / TEXT / MEDIUMTEXT / LONGTEXTBLOB:存原始二进制(无字符集,图片、文件),分 TINYBLOB / BLOB / MEDIUMBLOB / LONGBLOBTEXT/BLOB 本身的大量数据存在溢出页(单独地方) ,不会全部塞进 65535 的行里面; 但是它依然占 1 个列名额 ,会算进 1017 / 4096 的列计数里! 并且它在本行里只放一个指针(9~12 字节),这一小段指针是计入 65535 行大小的
它们不是一定有的
只要每一列的存储长度控制在 64 字节以内,总和就能卡在 65535 以内,这样就能保证列数能达到1017吗?
InnoDB自己还有一层页内本地行上限:8126
场景 A:1017 列里面包含 TEXT/BLOB TEXT/BLOB 只有指针占一点点字节,大内容甩出去。 可以把页内本地大小压到 8126 以内,同时总列数凑到 1017、Server 行大小≤65535 → 建表成功。
场景 B:1017 列全是普通 CHAR/VARCHAR(无 TEXT/BLOB) 所有数据都在页内,就算总和 65088<65535,远超 8126,直接报错,建不成!