InnoDB-记录行

前言

  大家好,我是xicheng。从这篇文章开始,会陆续地更新MySQL相关的相关文章。帮助大家提升基础的同时,顺便就准备了面试的八股文,开始发车。

常见存储引擎

  在讲InnoDB之前先看一下MySQL有哪些常见的存储引擎。
  InnoDB:支持事务,行锁设计,支持外键,通过MVCC获取高并发性,5.5.8开始成为MySQL的默认存储引擎。提供插入缓存,二次写,自适应哈希索引,预读等高性能,高可用功能。主要面向OLTP(在线事务处理)应用。表都是根据主键顺序组织存放的,这种方式叫索引组织表。
  MyISAM:不支持事务,存储引擎表由MYD与MYI组成,前者存储数据文件,后者存储索引文件。主要面向OLAP(联机分析处理)应用。
  Memory:数据放内存中,速度非常快,只支持表锁,并发性能差,索引默认使用哈希索引。
  Archive:只支持SELECT与INSERT。适合存储归档数据。
  NDB:集群存储引擎,数据全放内存中,JOIN操作是在Server层完成而不是存储引擎层。
  Federated:不存放数据,指向远程数据库上的表。只支持MySQL数据库表,不支持其它数据库的表。

选择合适的存储引擎

  需要支持事务,热备份,快速的崩溃恢复就选择InnoDB。
  不需要支持事务,基本只有INSERT与SELECT,例如日志表。可以选择MyISAM。

行格式

  包括COMPACT,REDUNDANT,DYNAMIC(MySQL8.0默认格式),COMPRESSED
  InnoDB1.0.x版本的文件格式定义为Barracuda,之前的版本定义为Antelope。Barracuda文件格式包含了Antelope文件格式,并引入了DYNAMIC,COMPRESSED两种行格式。如下图所示。


COMPACT

行结构示意图

  • 变长字段长度列表
    • 存的是各变长字段的真实数据占用的字节数。并按字段顺序逆序存放。
    • 当maxlen (可变字段一个字符所需的字节数) * m(该字段最多存储的字符数) > 255,且L(真实存的字节数)> 127时,变长字段使用2字节记录长度。否则使用一个字节记录长度。
  • NULL值列表
    • 每列占用一个二进制位,按照字段顺序逆序排序,值为1表示该列的值为NULL。值为0表示该列的值不为NULL。
    • NULL值列表必须用整数字节表示,若使用的二进制位数不足整数字节时,则在高位补0。
  • 记录头信息,固定由5个字节组成,如下表所示。
名称 大小(位) 描述
预留位1 1 没有使用
预留位 21 没有使用
deleted_flag 1 标识该条记录是否被删除
min_rec_flag 1 B+树中每层非叶子节点的最小的目录项都会添加该标记
n_owned 4 1页记录会被分为若干组,每组中有一条记录的该值代表该组中所有记录的条数。其余记录的该值为0
heap_no 13 当前记录在页面堆中的相对位置
record_type 3 0:普通记录,1:B+树非叶子节点的目录条数,2:Infimum记录(下边界,记录比该页中任何主键值都要小的值),3:Supremum记录(上边界,记录比该页中任何主键值都要大的值,构成了页中记录的边界)
next_record 16 从当前记录的真实数据到下⼀条记录的真实数据的地址偏移量。这样向左读取就是记录头信息,向右读取就是真实数据。

行记录的真实数据
  除了有用户定义的列外,还有若干隐藏列,如下表所示。

列名 是否必须 大小(字节) 描述
DB_ROW_ID 6 行id。如果⽤户没有定义主键,则取⼀个Unique键作为主键,如果表中无Unique键,InnoDB会默认添加⼀个DB_ROW_ID隐藏列作为主键
DB_TRX_ID 6 事务idDB_ROLL_PTR是7回滚指针
DB_ROLL_PTR 7 回滚指针

  行记录的真实数据的顺序一次是:DB_ROW_ID,DB_TRX_ID,DB_ROLL_PTR,用户定义的列1的值,用户定义的列2的值,...,用户定义的列n的值。其余行格式的真是数据也是这个顺序。
CHAR存储格式
  当采用定长编码的字符集时,该列用的字节数不会被加到变长字段长度列表中。采用变长编码的字符集时,则会加到其中。
  采用变长编码字符集时,CHAR(M)至少会占用M个字节。

REDUNDANT

行结构示意图


行记录的额外信息

  • 字段长度偏移列表
      按照相邻两个偏移量的差值来计算各个列值的长度。并按字段顺序逆序存放。
      比如,某一行的字段长度偏移列表为 18 15 0D 07 ,因为是逆序存放的,则按列排序就是 07 0D 15 18。
    • 第1列长度就是0x07个字节,即7个字节。
    • 第2列长度就是(0x0D - 0x07)个字节,即6个字节。
    • 第3列长度就是(0x15 - 0x0D)个字节,即8个字节。
    • 第3列长度就是(0x18 - 0x15)个字节,即3个字节。
  • 记录头信息,固定由6个字节组成,如下表所示。
名称 大小(位) 描述
预留位1 1 没有使用
预留位2 1 没有使用
deleted_flag 1 标识该条记录是否被删除
min_rec_flag 1 B+树中每层非叶子节点的最小的目录项都会添加该标记
n_owned 4 1页记录会被分为若干组,每组中有一条记录的该值代表该组中所有记录的条数。其余记录的该值为0
heap_no 13 当前记录在页面堆中的相对位置
n_field 10 记录中列的数量
byte_offs_flag 1 标记字段长度偏移列表中每个列对应的偏移量使用一个字节还是两个字节来表示
真实数据占用空间大小为n
当n<=127时,值为1,用1个字节表示偏移量
当127<n<=215 时,值为0,用2个字节表示偏移量
当n>215 时,值为0,记录的一部分已放入溢出区,用2个字节表示偏移量
next_record 16 从当前记录的真实数据到下⼀条记录的真实数据的地址偏移量。这样向左读取就是记录头信息,向右读取就是真实数据
  • NULL值处理
      如果列对应的偏移量值的第1个比特位为1,则该列值就是NULL,否则就不是NULL。
      如果存储NULL值的字段是定长类型,如CHAR(M),则字段对应的真实数据会使用0填充。
      如果存储NULL值的字段是变长类型,如VARCHAR(M),则不在行记录的真实部分占用任何的存储空间。
    CHAR存储格式
      CHAR(M)占用空间 = 该字符集表示一个字符最多需要的字节数 * M。例如,utf-8的CHAR(10)占用30个字节。gbk的CHAR(10)占用20个字节。

溢出列

  结构示意图如下。



  每页额外需要132个字节存储其它数据。每条记录需要固定用27个字节存储存储额外信息。
  每页至少需要存2条记录。则有如下不等式:132 + 2 * (27 + n) < 16KB。解出n < 8099。当这列中存储的数据占用空间>=8099字节时,就会成为溢出列。

DYNAMIC

  与COMPACT类似,区别是,处理溢出列时,会把该列的所有数据都存到溢出列中。

COMPRESSED

  与DYNAMIC类似,区别是,会采用压缩算法对页面进行压缩。

结尾

  MySQL通过InnoDB的记录行开了个头,希望大家能持续关注下去。下一篇MySQL文章讲InnoDB-数据页的存储结构。
  感谢各位人才的点赞、收藏和评论,干货文章持续更新中,下篇文章再见!

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 212,718评论 6 492
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 90,683评论 3 385
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 158,207评论 0 348
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 56,755评论 1 284
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 65,862评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 50,050评论 1 291
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,136评论 3 410
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,882评论 0 268
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,330评论 1 303
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,651评论 2 327
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,789评论 1 341
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,477评论 4 333
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,135评论 3 317
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,864评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,099评论 1 267
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 46,598评论 2 362
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 43,697评论 2 351

推荐阅读更多精彩内容