mysql的 可变长字段定义在255字节长度 前后变化的过程

Posted 翔之天空

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了mysql的 可变长字段定义在255字节长度 前后变化的过程相关的知识,希望对你有一定的参考价值。

 

 

参考:https://dev.mysql.com/doc/refman/5.7/en/innodb-online-ddl-operations.html

https://dev.mysql.com/doc/internals/en/innodb-field-start-offsets.html

https://dev.mysql.com/doc/internals/en/innodb-extra-bytes.html

https://www.cnblogs.com/vinchen/p/3320002.html

 

问题结论:在mysql的varchar变更长度是 如果在0到255个字节内 变更长度 是可以直接加上的 瞬时完成。但如果 是0到255字段 需要变更为 大于255以上字节的长度时  需要有copy和锁表的过程。

 

问题原因:因为在ibd文件的行记录(User Records)里,如果变长的字段 是0到255字节范围 用一个字节表示,如果大于255 小于65535的话 用两个字节表示。

 

问题测试:

--注释1:若字段定义的最大长度小于等于255,用1个字节表示其长度
--1、建立测试表(utf8mb4)和数据,address字段定义为50*4=200字节(小于255字节),   插入的数据: id为1的address是 142字节、 id为2的address是5个字节  
create table test_record_byte_table(id int, name varchar(10),  address varchar(50),class char(3));
insert into test_record_byte_table values(1,'xiaoming','mars火星火星火星火星火星火星火星火星火星火星火星火星火星火星火星火星火星火星火星火星火星火星火星','1-1');
insert into test_record_byte_table values(2,'xiaohong','earth','3-1');

[root@localhost][wangx_test]> show table status like 'test_record_byte_table'\\G
*************************** 1. row ***************************
           Name: test_record_byte_table
         Engine: InnoDB
        Version: 10
     Row_format: Dynamic
           Rows: 2
Avg_row_length: 8192
    Data_length: 16384
Max_data_length: 0
   Index_length: 0
      Data_free: 0
Auto_increment: NULL
    Create_time: 2021-01-07 13:47:22
    Update_time: 2021-01-07 13:47:23
     Check_time: NULL
      Collation: utf8mb4_general_ci
       Checksum: NULL
Create_options:
        Comment:
1 row in set (0.00 sec)



[root@localhost wangx_test]# hexdump -C test_record_byte_table.ibd  
.....
0000c070  73 75 70 72 65 6d 75 6d  03 8e 08 00 00 00 10 00  |supremum........|    /*第一条记录*/  长度标识 倒序 class的3字节、address的142字节(用一个字节8e标识实际长度)、name的8字节
0000c080  b9 00 00 00 00 03 16 00  00 00 01 4e 24 ec 00 00  |...........N$...|    /*第一条记录*/  主键为00 00 00 00 03 16 (这里没有自定义主键,所以默认 6字节的 rowid做主键)
0000c090  00 37 01 10 80 00 00 01  78 69 61 6f 6d 69 6e 67  |.7......xiaoming|
0000c0a0  6d 61 72 73 e7 81 ab e6  98 9f e7 81 ab e6 98 9f  |mars............|
0000c0b0  e7 81 ab e6 98 9f e7 81  ab e6 98 9f e7 81 ab e6  |................|
0000c0c0  98 9f e7 81 ab e6 98 9f  e7 81 ab e6 98 9f e7 81  |................|
0000c0d0  ab e6 98 9f e7 81 ab e6  98 9f e7 81 ab e6 98 9f  |................|
0000c0e0  e7 81 ab e6 98 9f e7 81  ab e6 98 9f e7 81 ab e6  |................|
0000c0f0  98 9f e7 81 ab e6 98 9f  e7 81 ab e6 98 9f e7 81  |................|
0000c100  ab e6 98 9f e7 81 ab e6  98 9f e7 81 ab e6 98 9f  |................|
0000c110  e7 81 ab e6 98 9f e7 81  ab e6 98 9f e7 81 ab e6  |................|
0000c120  98 9f e7 81 ab e6 98 9f  e7 81 ab e6 98 9f 31 2d  |..............1-|
0000c130  31 03 05 08 00 00 00 18  ff 36 00 00 00 00 03 17  |1........6......|    /*第二条记录*/  长度标识 倒序 class的3字节、address的5字节、name的8字节
0000c140  00 00 00 01 4e 25 ed 00  00 00 3a 01 10 80 00 00  |....N%....:.....|    /*第二条记录*/  主键为00 00 00 00 03 17 (这里没有自定义主键,所以默认 6字节的 rowid做主键)
0000c150  02 78 69 61 6f 68 6f 6e  67 65 61 72 74 68 33 2d  |.xiaohongearth3-|
0000c160  31 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  |1...............|
0000c170  00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  |................|
*
0000fff0  00 00 00 00 00 70 00 63  91 fd e8 3e 59 fe 76 70  |.....p.c...>Y.vp|
00010000  00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  |................|
*
00018000



--注释2:若字段定义的最大长度大于255,但实际使用长度小于128,用1个字节表示其实际长度。 参考 /*第二条记录*/
--注释3:若字段定义的最大长度大于255,并且实际使用长度大于等于128或者若字段是大字段(blob、text等),用2字节表示其长度。 最高位(第15位)总是1 、次高位(第14位)为0表示行内存储、剩余14位(0~13)表示真实长度。  参考 /*第一条记录*/
--2、变更address字段长度为500*4=2000字节(大于255字节),但实际值长度不变
[root@localhost][wangx_test]> alter table test_record_byte_table modify address varchar(500);
Query OK, 2 rows affected (0.02 sec)          /*可以看到影响的行数为2行 即全部数据,说明影响全表操作*/
Records: 2  Duplicates: 0  Warnings: 0

0000c070  73 75 70 72 65 6d 75 6d  03 8e 80 08 00 00 00 10  |supremum........|    /*第一条记录*/ address定义大于255字节且实际长度142也大于128字节,所以这里两个字节表示实际长度80 8e
                                            / 80 8e 转换2进制为 1000 0000 1000 1110,其中第一位总是1,第二位是0表示行内存储,剩余14位表示实际长度  00 0000 1000 1110 转10进制为142
0000c080  00 b9 00 00 00 00 03 18  00 00 00 01 4e 2e f4 00  |............N...|    /*第一条记录*/  主键从00 00 00 00 03 16 变为了 00 00 00 00 03 18 
                                                                                                  rowid主键变化 从侧面说明 该行数据有迁移的过程
0000c090  00 00 3a 01 10 80 00 00  01 78 69 61 6f 6d 69 6e  |..:......xiaomin|
0000c0a0  67 6d 61 72 73 e7 81 ab  e6 98 9f e7 81 ab e6 98  |gmars...........|
0000c0b0  9f e7 81 ab e6 98 9f e7  81 ab e6 98 9f e7 81 ab  |................|
0000c0c0  e6 98 9f e7 81 ab e6 98  9f e7 81 ab e6 98 9f e7  |................|
0000c0d0  81 ab e6 98 9f e7 81 ab  e6 98 9f e7 81 ab e6 98  |................|
0000c0e0  9f e7 81 ab e6 98 9f e7  81 ab e6 98 9f e7 81 ab  |................|
0000c0f0  e6 98 9f e7 81 ab e6 98  9f e7 81 ab e6 98 9f e7  |................|
0000c100  81 ab e6 98 9f e7 81 ab  e6 98 9f e7 81 ab e6 98  |................|
0000c110  9f e7 81 ab e6 98 9f e7  81 ab e6 98 9f e7 81 ab  |................|
0000c120  e6 98 9f e7 81 ab e6 98  9f e7 81 ab e6 98 9f 31  |...............1|
0000c130  2d 31 03 05 08 00 00 00  18 ff 35 00 00 00 00 03  |-1........5.....|    /*第二条记录*/  address定义大于255字节,但实际没有超过128字节 还是一个字节(05)标识实际长度
0000c140  19 00 00 00 01 4e 2e f4  00 00 00 3a 01 1f 80 00  |.....N.....:....|    /*第二条记录*/  主键从00 00 00 00 03 17变为了 00 00 00 00 03 19
                                                                                                   rowid主键变化 从侧面说明 该行数据有迁移的过程
0000c150  00 02 78 69 61 6f 68 6f  6e 67 65 61 72 74 68 33  |..xiaohongearth3|
0000c160  2d 31 00 00 00 00 00 00  00 00 00 00 00 00 00 00  |-1..............|
0000c170  00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  |................|
*
0000fff0  00 00 00 00 00 70 00 63  07 88 03 03 59 fe 97 f7  |.....p.c....Y...|
00010000  00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  |................|
*
00018000

 

以上是关于mysql的 可变长字段定义在255字节长度 前后变化的过程的主要内容,如果未能解决你的问题,请参考以下文章

Mysql varchar字段长度越大越好吗?

MySQL学习记录02常用数据类型

mysql全部基本数据类型

mysql varchar最大是多少?

小白学习MySQL - varchar类型字段为什么经常定义成255?

MySQL 基础--字符类型