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字节长度 前后变化的过程的主要内容,如果未能解决你的问题,请参考以下文章