04 mysql innodb record

前言

最近看到了 何登成 大佬的 "深入MySQL源码 -- Step By Step" 的 pdf 呵呵 似乎是找到了一些 方向

之前对于 mysql 方面的东西, 更多的仅仅是简单的使用[业务中的各种增删改查], 以及一些面试题的背诵

这里会参照 MySQL Internals Manual 来大致的看一下 innodb 里面的 record 的存储相关, 这些是深入了解 mysql 的基础

我们这里主要是会了解一下两种 RowFormat : Redundant 和 Compact

本文内容对应的是 mysql调试的一些基础方法 里面的 查看一下 rec 的数据信息

MySQL Internals Manual - 22.1 InnoDB Record Structure

以下截图参照自 MySQL Internals Manual

这里的说明是基于 RowFormat - Redundant

总的来说一个 record 分成了三个部分 : 各个字段的偏移(Field Start Offsets), 元数据信息(Extra Bytes), 记录信息(Field Contents)

Field Start Offsets : 描述的是 record 中的各个字段在 Field Contents 中的偏移, 以此偏移可以确认各个字段的数据信息

Extra Bytes : 描述的是 record 的元数据, 包括了 删除标记, minRecord标记, 字段数量, "Field Start Offsets" 的单位, 记录编号, 下一个记录的偏移 等等信息

Field Contents : 里面存储的是具体的数据信息

22.1.1.3 FIELD CONTENTS 里面介绍了一个实例的案例, 剖析一个实际的记录在内存中的数据分布情况, 以及拆解每一个字节的逻辑意义, 可以移步文档看一下, 这里就不截图了, 请自行查阅文档

源码中的说明 remOrec.cc | remOrec.ic | remOrec.h

我们再来根据源码中的注释结合 来看一下

里面注释写的相当详尽, 因此 建议多读注释, 以方便理解

"深入MySQL源码 -- Step By Step" 里面也提到了 "不放过源码中的每一处注释"

RowFormat - Redundant

注释里面描述的内容 和 上面 MySQL Internals Manual - 22.1 InnoDB Record Structure 一致

Extra Bytes 的结构信息

RowFormat - Compact

注释里面描述的内容 就是 Compact 的 RowFormat 的格式了, MySQL Internals Manual 上面我没有找到

总的来说一个 record 分成了三个部分 : 各个字段的偏移(Field Start Offsets), 元数据信息(Extra Bytes), 记录信息(Field Contents)

Field Start Offsets : 描述的是 record 中的各个长度可变字段在 Field Contents 中的偏移, table元数据中固定字段偏移 结合 此偏移 可以确认所有字段的偏移, 进而可以确认各个字段的数据信息

Extra Bytes : 描述的是 record 的元数据, 包括了 null字段标记, 删除标记, minRecord标记, 记录编号, 下一个记录的偏移 等等信息

Field Contents : 里面存储的是具体的数据信息

Extra Bytes 的结构信息

RowFormat - Redundant 实际案例剖析

复制代码
# ROW_FORMAT = Redundant 的内存情况
(lldb) x 0x12c694000 -c 0x100
0x12c694000: 1c 18 8c aa 00 00 00 03 ff ff ff ff ff ff ff ff  ...�....��������
0x12c694010: 00 00 00 00 00 1a b2 d5 45 bf 00 00 00 00 00 00  ......��E�......
0x12c694020: 00 00 00 00 00 07 00 02 00 c6 00 04 00 00 00 00  .........�......
0x12c694030: 00 ad 00 02 00 01 00 02 00 00 00 00 00 00 00 00  .�..............
0x12c694040: 00 00 00 00 00 00 00 00 00 17 00 00 00 07 00 00  ................
0x12c694050: 00 02 00 f2 00 00 00 07 00 00 00 02 00 32 08 01  ...�.........2..
0x12c694060: 00 00 03 00 88 69 6e 66 69 6d 75 6d 00 09 03 00  .....infimum....
0x12c694070: 08 03 00 00 73 75 70 72 65 6d 75 6d 00 1a 15 11  ....supremum....
0x12c694080: 0a 04 00 00 10 0b 00 ad 80 00 00 01 00 00 00 00  .......�........
0x12c694090: 3b 07 87 00 00 01 3a 01 10 80 00 00 1c 6a 65 72  ;.....:......jer
0x12c6940a0: 72 79 19 15 11 0a 04 00 00 18 0b 00 74 80 00 00  ry..........t...
0x12c6940b0: 02 00 00 00 00 3b 08 88 00 00 01 3e 01 10 80 00  .....;.....>....
0x12c6940c0: 00 16 6c 75 63 79 00 00 00 00 00 00 00 00 00 00  ..lucy..........
0x12c6940d0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ................
0x12c6940e0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ................
0x12c6940f0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ................

# 0x12c694050
0x12c694050: 00 02 00 f2 00 00 00 07 00 00 00 02 00 32 08 01  ...�.........2..
0x12c694060: 00 00 03 00 88 69 6e 66 69 6d 75 6d 00 09 03 00  .....infimum....
0x12c694070: 08 03 00 00 73 75 70 72 65 6d 75 6d 00 1a 15 11  ....supremum....
0x12c694080: 0a 04 00 00 10 0b 00 ad 80 00 00 01 00 00 00 00  .......�........
0x12c694090: 3b 07 87 00 00 01 3a 01 10 80 00 00 1c 6a 65 72  ;.....:......jer
0x12c6940a0: 72 79 19 15 11 0a 04 00 00 18 0b 00 74 80 00 00  ry..........t...
0x12c6940b0: 02 00 00 00 00 3b 08 88 00 00 01 3e 01 10 80 00  .....;.....>....
0x12c6940c0: 00 16 6c 75 63 79 00 00 00 00 00 00 00 00 00 00  ..lucy..........


# infimum = PAGE_OLD_INFIMUM = 0x65
08 : offset of `infimum`
01 : deleted_flag = 0, min_rec_flag = 0, n_owned = 1
00 00 03 : heap_no = 0, n_fields = 1, 1byte_offs_flag = 1
00 88 : next record pointer -> jerry
69 6e 66 69 6d 75 6d 00 : infimum

# supremum = PAGE_OLD_SUPREMUM = 0x74
09 : offset of `supremum`
03 : deleted_flag = 0, min_rec_flag = 0, n_owned = 3
00 08 03 : heap_no = 1, n_fields = 1, 1byte_offs_flag = 1
00 00 : next record pointer -> self
73 75 70 72 65 6d 75 6d 00 : supremum

# record jerry : 0x12c694088 # 格式为 redundant row format
1a 15 11 0a 04 : field offset of id, trx_id, poll_ptr, age, name
00 : deleted_flag = 0, min_rec_flag = 0, n_owned = 0
00 10 0b : heap_no = 2, n_fields = 5, 1byte_offs_flag = 1
00 ad : next record offset -> record lucy

id = 80 00 00 01 = 1
trx_id = 00 00 00 00 3b 07 = 15111
poll_ptr = 87 00 00 01 3a 01 10
age = 80 00 00 1c = 28
name = 6a 65 72 72 79 = jerry

# record lucy : 0x12c6940ad # 格式为 redundant row format
19 15 11 0a 04 : field offset of id, trx_id, poll_ptr, age, name
00 : deleted_flag = 0, min_rec_flag = 0, n_owned = 0
00 18 0b : heap_no = 3, n_fields = 5, 1byte_offs_flag = 1
00 74 : next record offset -> supremum

id = 80 00 00 02 = 2
trx_id = 00 00 00 00 3b 08 = 15112
poll_ptr = 88 00 00 01 3e 01 10
age = 80 00 00 16 = 22
name = 6c 75 63 79 = lucy

RowFormat - Compact 实际案例剖析

复制代码
# user 对应的数据 当前页的数据信息, 拆解
(lldb) x 0x1286cc000 -c 0x120
0x1286cc000: 10 aa fb 30 00 00 00 03 ff ff ff ff ff ff ff ff  .��0....��������
0x1286cc010: 00 00 00 00 00 1a a2 7d 45 bf 00 00 00 00 00 00  ......�}E�......
0x1286cc020: 00 00 00 00 00 06 00 02 00 b9 80 04 00 00 00 00  .........�......
0x1286cc030: 00 a0 00 02 00 01 00 02 00 00 00 00 00 00 00 00  .�..............
0x1286cc040: 00 00 00 00 00 00 00 00 00 16 00 00 00 06 00 00  ................
0x1286cc050: 00 02 00 f2 00 00 00 06 00 00 00 02 00 32 01 00  ...�.........2..
0x1286cc060: 02 00 1c 69 6e 66 69 6d 75 6d 00 03 00 0b 00 00  ...infimum......
0x1286cc070: 73 75 70 72 65 6d 75 6d 05 00 00 00 10 00 21 80  supremum......!.
0x1286cc080: 00 00 01 00 00 00 00 2b 07 04 00 00 01 56 04 7b  .......+.....V.{
0x1286cc090: 80 00 00 1c 6a 65 72 72 79 04 00 00 00 18 ff d0  ....jerry.....��
0x1286cc0a0: 80 00 00 02 00 00 00 00 35 04 83 00 00 01 36 01  ........5.....6.
0x1286cc0b0: 10 80 00 00 16 6c 75 63 79 00 00 00 00 00 00 00  .....lucy.......
0x1286cc0c0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ................
0x1286cc0d0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ................
0x1286cc0e0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ................
0x1286cc0f0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ................
0x1286cc100: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ................
0x1286cc110: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ................

# 0x1286cc050
0x1286cc050: 00 02 00 f2 00 00 00 06 00 00 00 02 00 32 01 00  ...�.........2..
0x1286cc060: 02 00 1c 69 6e 66 69 6d 75 6d 00 03 00 0b 00 00  ...infimum......
0x1286cc070: 73 75 70 72 65 6d 75 6d 05 00 00 00 10 00 21 80  supremum......!.
0x1286cc080: 00 00 01 00 00 00 00 2b 07 04 00 00 01 56 04 7b  .......+.....V.{
0x1286cc090: 80 00 00 1c 6a 65 72 72 79 04 00 00 00 18 ff d0  ....jerry.....��
0x1286cc0a0: 80 00 00 02 00 00 00 00 35 04 83 00 00 01 36 01  ........5.....6.
0x1286cc0b0: 10 80 00 00 16 6c 75 63 79 00 00 00 00 00 00 00  .....lucy.......


# infimum = PAGE_NEW_INFIMUM = 0x63
# infimum : 0x1286cc063
0x0 : delete_flag & min_rec_flag
0x1 : number of records owned by the record
0b 0000 0000 0000 0 = 0 = order number of this record
0b 010 = infimum
0x 00 1c = next record offset -> jerry
69 6e 66 69 6d 75 6d 00 = infimum

# supremum = PAGE_NEW_SUPREMUM = 0x70
# supremum : 0x1286cc070
0x0 : delete_flag & min_rec_flag
0x3 : number of records owned by the record
0b 0000 0000 0000 1 = 1 = order number of this record
0b 011 = supremum
0x 00 00 = next record offset -> self
73 75 70 72 65 6d 75 6d = supremum

# record jerry : 0x1286cc07f # 格式为 compact row format
0x05 : lengthOf('jerry')
0x00 = nulls
0x0 : delete flag
0x0 : number of records owned by the record
0b 0000 0000 0001 0 = 2 = order number of this record
0b 000 = conventional
0x 00 21 : next record offset -> record lucy

rec = 0x80
id = 0x 80 00 00 01 = 1
trx_id = 0x 00 00 00 00 2b 07 = 11015
poll_ptr = 0x 04 00 00 01 56 04 7b
age = 0x 80 00 00 1c = 28
name = 6a 65 72 72 79 = jerry

# record lucy : 0x1286cc0a0 # 格式为 compact row format
0x04 : lengthOf('lucy')
0x00 = nulls
0x0 : delete flag
0x0 : number of records owned by the record
0b 0000 0000 0001 1 = 3 = order number of this record
0b 000 = conventional
0x ff d0 : next record offset -> supremum

rec = 0x80
id = 0x 80 00 00 02 = 2
trx_id = 0x 00 00 00 00 35 04 = 13572
poll_ptr = 0x 83 00 00 01 36 01 10
age = 0x 80 00 00 16 = 22
name = 6c 75 63 79 = lucy

参考

MySQL Internals Manual

深入MySQL源码 -- Step By Step

mysql调试的一些基础方法

相关推荐
叁沐39 分钟前
MySQL 05 深入浅出索引(下)
mysql
陈卓4101 小时前
MySQL-主从复制&分库分表
android·mysql·adb
你都会上树?2 小时前
MySQL MVCC 详解
数据库·mysql
长征coder3 小时前
AWS MySQL 读写分离配置指南
mysql·云计算·aws
ladymorgana3 小时前
【docker】修改 MySQL 密码后 Navicat 仍能用原密码连接
mysql·adb·docker
PanZonghui3 小时前
Centos项目部署之安装数据库MySQL8
linux·后端·mysql
GreatSQL社区4 小时前
用systemd管理GreatSQL服务详解
数据库·mysql·greatsql
掘根4 小时前
【MySQL进阶】错误日志,二进制日志,mysql系统库
数据库·mysql
weixin_438335404 小时前
基础知识:mysql-connector-j依赖
数据库·mysql
小明铭同学4 小时前
MySQL 八股文【持续更新ing】
数据库·mysql