Row size too large. The maximum row size for the used table type, not counting BLOBs, is 65535.

文章目录

  • 问题描述
  • 分析
    • 3、结论
  • 解决方案
  • 拓展
    • 1、为什么我们经常使用varchar(255),不使用varchar(256)?
    • 2、MySQL列数限制
    • 3、int类型的占用空间的大小范围
    • 4、验证NULL占用1个字节

问题描述

在新建表或者修改表varchar字段长度的时候,出现下面这个错误

Row size too large. The maximum row size for the used table type, not counting BLOBs, is 65535. This includes storage overhead, check the manual. You have to change some columns to TEXT or BLOBs

Row size too large. The maximum row size for the used table type, not counting BLOBs, is 65535._第1张图片
大概意思就是行大小太大,不能超过65535,这个是怎么来的?其实就是字符串的最大长度,但为什么不能设置为最大,我们改为改为21842就正常了,这是为什么?下面我们一起来分析一下


分析

首先来了解几个MySQL规则,对我们的字符数有影响的规则

  • 编码规则

不同字符集下,占用空间不一样
gbk编码中,1个字符占用2个字节
utf8编码(默认)中,1个字符占用3个字节
utf8mb4编码中,1个字符占用4个字节

  • 存储规则

varchar除了存储字符,还需要额外的空间来存储长度和是否为NULL,分别占用1-2字节和1字节

  • 行大小限制

MySQL 表的内部表示具有 65,535 字节的最大行大小限制,即使存储引擎能够支持更大的行。 BLOB 和 TEXT列仅对行大小限制贡献 9 到 12 个字节,因为它们的内容与行的其余部分分开存储

接下来,我们进行验证下

根据行最大65535字节,我们选择utf8编码,那我们最多可以设置的字符数为65535/3=21845
Row size too large. The maximum row size for the used table type, not counting BLOBs, is 65535._第2张图片
还是报错了,因为我们还需要减去额外的存储(长度和是否为NULL),65535-3=65532/2=21844,设置成21844就成功了

3、结论

至此,我们就知道为什么长度改为21842就没报错了
计算规则=(65535-4-2-1)/3=21,842.66666666667,向下取整,就是21842
说明:int占用4个字节,varchar的长度和是否为NULL占用3个字节,使用了utf8编码,1个字符占用3个字节

最终我们执行正确的SQL语句

CREATE TABLE `all_type_forlan` (
  `id` int(20) NOT NULL COMMENT 'id',
  `base_info` varchar(21842) DEFAULT NULL COMMENT '基本详细',
  PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

解决方案

  • 如果长度需要加长,将字段类型改为TEXT或BLOB
  • 如果只是想设置一个最大值,那可以根据计算规则进行调整

拓展

1、为什么我们经常使用varchar(255),不使用varchar(256)?

首先我们使用的varchar,除了存储字符内容,还需要额外存储长度和是否为NULL
因为varchar类型的字段长度在超过255后,需要2个字节来存储长度,因为1个字节=8位,可以表示的长度为255,2个字节=16位,可以表示的长度为65535
所以varchar(256)会比varchar(255)多占用1个字节来存储长度

2、MySQL列数限制

MySQL 对每个表有 4096 列的硬性限制,但对于给定的表,有效最大值可能会更少,因为表的最大行大小限制了列的数量

3、int类型的占用空间的大小范围

Row size too large. The maximum row size for the used table type, not counting BLOBs, is 65535._第3张图片

4、验证NULL占用1个字节

我们定义两个字段,tinyint和varchar
tinyint占用1个字节、varchar的长度和是否为NULL占用3个字节

计算规则:65535-1-3=65531/3=21,843.66666666667,向下取整,最多只能21843
所以长度设为21844就会报错,如下:
Row size too large. The maximum row size for the used table type, not counting BLOBs, is 65535._第4张图片
我们把varchar字段设为不是null,计算规则:65535-1-2=65532/3=21844,设为21844就成功了
``

你可能感兴趣的:(数据库,mysql,数据库,sql)