签到成功

知道了

CNDBA社区CNDBA社区

MySQL 行记录 最大长度 说明

2023-10-15 15:34 1277 0 原创 MySQL
作者: dave

1 理论说明

在官方文档里,提到MySQL的行记录的最大长度:65535 bytes. http://www.cndba.cn/cndba/dave/article/131459

The internal representation of a MySQL table has a maximum row size limit of 65,535 bytes.
https://dev.mysql.com/doc/refman/5.7/en/column-count-limit.html

这里的65535 是所有列共享的长度,即MySQL 表中所有列的长度加起来不能超过65535个字节。

在Mysql 5.0 之后,列的类型,比如varchar(20)指的是字符。而在不同的字符集中,字符和字节的关系也不一样,在utf8字符集中,一个汉字占3个字节,新的utf8mb4字符集中一个汉字占4个字节。所以如果列的字符串只保存英文,那么长度是一样的,但如果有中文,就会有出入。 http://www.cndba.cn/cndba/dave/article/131459

因此在不同的字符集下,能够列定义的最大长度就会有所不同。

可以使用LENGTH()和CHAR_LENGTH()统计字符串的长度:http://www.cndba.cn/cndba/dave/article/131459

http://www.cndba.cn/cndba/dave/article/131459

  1. LENGTH()是按照字节来统计的,
  2. CHAR_LENGTH()是按照字符来统计的。

2 操作示例

2.1 查看列类型的长度

理论部分可以查看如下两篇官方文档:

https://dev.mysql.com/doc/refman/5.7/en/innodb-row-format.html
https://dev.mysql.com/doc/refman/5.7/en/storage-requirements.html

mysql> SELECT @@innodb_default_row_format;
+-----------------------------+
| @@innodb_default_row_format |
+-----------------------------+
| dynamic                     |
+-----------------------------+
1 row in set (0.00 sec)

mysql> 

mysql> use ustc;
Database changed
mysql> CREATE TABLE cndba(c1 int);
Query OK, 0 rows affected (0.07 sec)

mysql>  show create table cndba/G
*************************** 1. row ***************************
       Table: cndba
Create Table: CREATE TABLE `cndba` (
  `c1` int(11) DEFAULT NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4
1 row in set (0.00 sec)

mysql> insert into cndba values(1);
Query OK, 1 row affected (0.02 sec)

我们这里可以看到,在utf8mb4 字符集下,INT 类型占1个字符(4个字节)。

mysql> select length(c1) from cndba;
+------------+
| length(c1) |
+------------+
|          1 |
+------------+
1 row in set (0.00 sec)

mysql> select char_length(c1) from cndba;
+-----------------+
| char_length(c1) |
+-----------------+
|               1 |
+-----------------+
1 row in set (0.00 sec)

mysql> SELECT * FROM INFORMATION_SCHEMA.INNODB_SYS_TABLES WHERE NAME LIKE 'ustc/cndba'/G
*************************** 1. row ***************************
     TABLE_ID: 43
         NAME: ustc/cndba
         FLAG: 33
       N_COLS: 4
        SPACE: 33
  FILE_FORMAT: Barracuda
   ROW_FORMAT: Dynamic
ZIP_PAGE_SIZE: 0
   SPACE_TYPE: Single
1 row in set (0.00 sec)

mysql>  SHOW TABLE STATUS/G
*************************** 1. row ***************************
           Name: cndba
         Engine: InnoDB
        Version: 10
     Row_format: Dynamic
           Rows: 1
 Avg_row_length: 16384
    Data_length: 16384
Max_data_length: 0
   Index_length: 0
      Data_free: 0
 Auto_increment: NULL
    Create_time: 2023-10-14 23:58:19
    Update_time: 2023-10-15 00:04:09
     Check_time: NULL
      Collation: utf8mb4_general_ci
       Checksum: NULL
 Create_options: 
        Comment: 
1 row in set (0.00 sec)

注意这里的16384, 是65535/4 的值。

其他类型的长度可以参考博客:

https://learn.blog.csdn.net/article/details/90675967http://www.cndba.cn/cndba/dave/article/131459http://www.cndba.cn/cndba/dave/article/131459

2.2 验证最大长度

VARCHAR(M) 能设置的最大长度
M 限制了 VARCHAR 能存储的字符串的最大长度,注意,是字符,不是字节,其有效值范围为 0 ~ 65535。

在 latin1 字符集下,M 最大就只能设置为 65532。http://www.cndba.cn/cndba/dave/article/131459

mysql> create table t (c1 varchar(65535)) charset latin1;
ERROR 1118 (42000): 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

mysql> create table t (c1 varchar(65532)) charset latin1;
Query OK, 0 rows affected (0.04 sec)

但是在utf8mb4 字符集下,建表时貌似没有实际进行检测,实际上并不是这样:

http://www.cndba.cn/cndba/dave/article/131459

mysql>  create table t (c1 varchar(1165533) not null) charset utf8mb4;
Query OK, 0 rows affected, 1 warning (0.07 sec)

mysql>  create table t3 (c1 varchar(1111165533) not null) charset utf8mb4;
Query OK, 0 rows affected, 1 warning (0.06 sec)

mysql>  create table t4 (c1 varchar(1111165533) ) charset utf8mb4;
Query OK, 0 rows affected, 1 warning (0.05 sec)

在低版本的MySQL中会有错误提示:

mysql> create table t (c1 varchar(65533) not null) charset utf8mb4;
ERROR 1074 (42000): Column length too big for column 'c1' (max = 16383); use BLOB or TEXT instead

但是在5.7 后期的版本中,会自动转换成text类型:http://www.cndba.cn/cndba/dave/article/131459

mysql> select @@version;
+------------+
| @@version  |
+------------+
| 5.7.25-log |
+------------+
1 row in set (0.00 sec)

mysql> create table t3(name varchar(65535));
Query OK, 0 rows affected, 1 warning (0.07 sec)

mysql> show warnings;
+-------+------+-----------------------------------------------+
| Level | Code | Message                                       |
+-------+------+-----------------------------------------------+
| Note  | 1246 | Converting column 'name' from VARCHAR to TEXT |
+-------+------+-----------------------------------------------+
1 row in set (0.00 sec)

表创建之后,实际上是有个警告的,直接对列进行类型转换:http://www.cndba.cn/cndba/dave/article/131459

mysql> desc t3/G
*************************** 1. row ***************************
  Field: name
   Type: mediumtext
   Null: YES
    Key: 
Default: NULL
  Extra: 
1 row in set (0.00 sec)

这里的类型也验证,mysql 自动将表T3 的列从varchar 转换成了mediumtext。

这里这里弄清楚之后就很好进一步验证了,我们创建个多列的表,长度加起来超过65535即可:

mysql> CREATE TABLE t1 (a VARCHAR(10000), b VARCHAR(10000), c VARCHAR(10000), d VARCHAR(10000), e VARCHAR(10000), f VARCHAR(10000), g VARCHAR(6000));
ERROR 1118 (42000): 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

这里就触发了我们的长度错误。

结论:

  1. 建表时,如果只有单列,在长度超过65535时,varchar会自动转换成text。
  2. 当表有多列的情况,所有列加起来的长度,不能超过65535,这里不包括TEXT、BLOB。

版权声明:本文为博主原创文章,未经博主允许不得转载。

用户评论
* 以下用户言论只代表其个人观点,不代表CNDBA社区的观点或立场
dave

dave

关注

人的一生应该是这样度过的:当他回首往事的时候,他不会因为虚度年华而悔恨,也不会因为碌碌无为而羞耻;这样,在临死的时候,他就能够说:“我的整个生命和全部精力,都已经献给世界上最壮丽的事业....."

  • 2283
    原创
  • 3
    翻译
  • 579
    转载
  • 196
    评论
  • 访问:8184003次
  • 积分:4428
  • 等级:核心会员
  • 排名:第1名
精华文章
    最新问题
    查看更多+
    热门文章
      热门用户
      推荐用户
        Copyright © 2016 All Rights Reserved. Powered by CNDBA · 皖ICP备2022006297号-1·

        QQ交流群

        注册联系QQ