19. 行记录

页的结构

 

File Header

 

记录

ROW_FORMAT

  1. REDUDENT:兼容老版本的InnoDB,MySQL 4.1版本之前
  2. COMPACT:MySQL 5.6 版本的默认格式
  3. COMPRESSED:支持压缩
  4. DYNAMIC:大对象记录优化,MySQL 5.7 版本默认格式 

 

COMPACT 结构

  • variable string length list
    • 变长字段列表,表示有多少个变长字段,且序号逆序显示
  • NULL flag
    • 是否有NULL值
  • rowid
    • B+树索引键值
  • trx id
    • 事物ID,6个字节
  • roll pointer
    • 回滚指针,7个字节

 

  • char 和 varchar 的区别

详细区别可以看之前的数据类型

结果:

在 多字节字符集 (如UTF8mb4)下:

  1. char(N) 中存储的数据的长度 范围 是 N ~ 4N ,当存储数据的长度 M , 未达到N 时,则填充空格(0x20),且空格的长度 取最小 的长度 N-M ,而 不是4N-M
  2. varchar(N) 则 不填充空格

注意: char 数据类型本来是定长数据,但是在多字节字符集下,表现的行为和varchar类似,失去了原来的优势,当数据更新变长后可能无法原地更新

 

  • 原地更新

    • 原地更新不会占用新的存储空间
    • 非原地更新需要删除(物理删除)原来的空间的数据,然后将更新后的数据插入到页的后面
    • 删除的数据的空间,会插入到 Free_List 链表的头部
    • 原地更新不会触发页的分裂

Free_List 是将页中被删除的空间串联在一起(组成一个链表 ),当有数据被插到页内时,先看一下Free_list中第一个空间的大小,如果空间合适,就将该记录插入到第一个空间中去,如果不合适,直接插入到页的尾部的剩余空间。( 不会去看Free_list的第二个空间 )。当该页的数据被插满了,不会马上进行分页,而是进行 reorganize 操作,即将页内的数据在内存中进行整理,然后覆盖原来的页(不影响性能)。所以InnoDB不需要碎片整理

 

  • Reorganize

 

DYNAMIC

DYNAMIC相比COMPACT,优化了大对象记录的存储。

假设有一条记录有A,B,C,D 四列,其中D列的是text类型,且含有2W个字节的长度。 

  • COMPACT

COMPACT会存储text中的前768个字节的数据,剩余的数据通过20个字节的指针指向溢出页

  • DYNAMIC

DYNAMIC直接通过20个字节的指针指向溢出页

相对COMPACT,DYNAMIC在一个页中存储的 记录数 更多(因为有768字节的prefix,一条记录的字节假设是800字节,那16K的页只能存放20条记录,而我测算可以存放80条记录),这样一来,B+树的高度可能会变高,读取的IO次数可能会变多。
一个页能存放的记录越多,则性能越优

 

heap number

  • heap number表示页中每个记录插入的顺序序号
    • 假设插入的数据是a, b, c, d, e, g;则对应的heap number是 2, 3, 4, 5, 6
    • 0和1被infimum和supermum所使用
      • infimum对应最小的heap_number
      • supermum对应最大的heap_number,随着数据的插入,该值会更新 
    • update对heap_number没有影响
    • heap_number是物理的,存储在row的 record_header 字段中

例子

-- 终端1
root@mysqldb 13:34:  [gavin]> create table test_heap(a int primary key);
Query OK, 0 rows affected (3.01 sec)

root@mysqldb 13:35:  [gavin]> insert into test_heap values (1);
Query OK, 1 row affected (0.02 sec)

root@mysqldb 13:35:  [gavin]> begin;
Query OK, 0 rows affected (0.00 sec)

root@mysqldb 13:35:  [gavin]> delete from test_heap where a=1; 
Query OK, 1 row affected (0.00 sec)

root@mysqldb 13:35:  [gavin]> show variables like "%innodb_status_output_locks%";
+----------------------------+-------+
| Variable_name              | Value |
+----------------------------+-------+
| innodb_status_output_locks | OFF   |
+----------------------------+-------+
1 row in set (0.00 sec)

root@mysqldb 13:35:  [gavin]> set global innodb_status_output_locks=1;    -- 打印详细锁信息

-- 终端2
root@mysqldb 13:34:  [(none)]> pager less    -- 使用类似linux中的less命令方式进行查看,可上下翻页
PAGER set to 'less'

root@mysqldb 14:01:  [(none)]> show engine innodb status\G
-- 省略其他输出
2 lock struct(s), heap size 1128, 1 row lock(s), undo log entries 1
MySQL thread id 8, OS thread handle 140402550052416, query id 36 localhost root
TABLE LOCK table `gavin`.`test_heap` trx id 18469 lock mode IX
RECORD LOCKS space id 29 page no 4 n bits 72 index PRIMARY of table `gavin`.`test_heap` trx id 18469 lock_mode X locks rec but not gap
Record lock, heap no 2 PHYSICAL RECORD: n_fields 3; compact format; info bits 32
 0: len 4; hex 80000001; asc     ;;    -- 插入的主键a=1
 1: len 6; hex 000000004825; asc     H%;;    0x4825的十进制就是18469,表示事务id
 2: len 7; hex 02000001500b9b; asc     P  ;;    -- roll pointer(回滚指针)
-- 省略其他输出
-- space id 29
-- page no 4
-- heap no 2

root@mysqldb 14:01:  [gavin]> rollback;
Query OK, 0 rows affected (0.00 sec)


-- heap no = 1 的一种情况
-- 终端1
root@mysqldb 14:05:  [gavin]> set transaction_isolation='repeatable-read';
Query OK, 0 rows affected (0.00 sec)

root@mysqldb 14:06:  [gavin]> begin;
Query OK, 0 rows affected (0.00 sec)

root@mysqldb 14:06:  [gavin]> select * from test_heap where a>1 for update;
Empty set (0.00 sec)

-- 终端2
root@mysqldb 14:01:  [(none)]> show engine innodb status\G
-- 省略其他输出
---TRANSACTION 18472, ACTIVE 5 sec    -- 事务活跃了5s
2 lock struct(s), heap size 1128, 2 row lock(s)
MySQL thread id 8, OS thread handle 140402550052416, query id 42 localhost root
TABLE LOCK table `gavin`.`test_heap` trx id 18472 lock mode IX
RECORD LOCKS space id 29 page no 4 n bits 72 index PRIMARY of table `gavin`.`test_heap` trx id 18472 lock_mode X
Record lock, heap no 1 PHYSICAL RECORD: n_fields 1; compact format; info bits 0
 0: len 8; hex 73757072656d756d; asc supremum;;    -- 一条伪记录

Record lock, heap no 2 PHYSICAL RECORD: n_fields 3; compact format; info bits 0
 0: len 4; hex 80000001; asc     ;;
 1: len 6; hex 000000004818; asc     H ;;
 2: len 7; hex 820000014d0110; asc     M  ;;
-- 省略其他输出
posted @ 2024-04-15 22:54  bingo-HF  阅读(6)  评论(0编辑  收藏  举报