MySQL 记录、页、索引的数据结构简析

引言本文在介绍 MySQL 内存中记录、页、索引、游标的数据结构的基础上,通过简单分析插入操作过程中行格式的转换介绍了不同数据结构的关系,其中不涉及加锁相关逻辑 。
原理记录概念InnoDB 存储引擎基于记录(record)存储,表明记录是根据行(row)格式存储 。
MySQL 中有行格式有以下三种存储方式:

  • Server 层的格式,这种格式与存储引擎没关系 , 适用于所有存储引擎 , 这种格式是操作数据必然要经过的一种格式,也是 Row 模式下 binlog 存储所使用的一种格式;
  • 索引元组格式,这种格式是 InnoDB 存储引擎在存取记录时一种记录格式的中间状态 , 它要么是从 Server 层转换而来,要是么转换为 Server 层的格式 。索引元组格式与索引一一对应 , 是内存中一种用来存储索引中所有列数据的数据结构,对应逻辑记录(tuple);
  • 物理存储记录格式,这种格式是一条记录在物理页面中的存储格式,也就是 Compact 格式 。这种格式与索引元组格式一一对应,对应物理记录(record) 。
因此:
  • 存数据时,发生以下转换:Server 层的格式 -> 索引元组格式 -> 物理存储记录格式;
  • 取数据时,发生以下转换:物理存储记录格式 -> 索引元组格式 -> Server 层的格式 。
个人理解存取数据时完成二进制到“字符串”的相互转换(忽略其他数据类型) , 相当于客户端与服务端交互时的编码与解码 。
数据结构内存中逻辑记录与其中的字段分别对应数据结构 dtuple_t 与 dfield_t 。
结构体定义如下所示 。
/** Structure for an SQL data tuple of fields (logical record) */struct dtuple_t { ulintn_fields; /*!< number of fields in dtuple */ ulintn_fields_cmp; /*!< number of fields which shouldbe used in comparison servicesof rem0cmp.*; the index searchis performed by comparing only thesefields, others are ignored; thedefault value in dtuple creation isthe same value as n_fields */ dfield_t* fields;/*!< fields */ UT_LIST_NODE_T(dtuple_t) tuple_list;/*!< data tuples can be linked into alist using this field */};其中:
  • ulint n_fields,表示列的数量;
  • dfield_t* fields,表示记录中的列 , 存储指向每一列真实数据的指针;
  • UT_LIST_NODE_T(dtuple_t) tuple_list,连接多个 dtuple_t,原因是每个索引对应一个 dtuple_t,比如 INSERT SQL 需要向主键索引和二级索引中都插入时 。
数据结构 dfield_t 中保存列的信息 。
/** Structure for an SQL data field */struct dfield_t{ void*data; /*!< pointer to data */ unsigned ext:1; /*!< TRUE=externally stored, FALSE=local */ unsigned len; /*!< data length; UNIV_SQL_NULL if SQL null */ dtype_ttype; /*!< type of data */};其中:
  • data,表示真实列数据的指针;
  • ext:1,如果是大记录(blob) , 则在外部页存储;
  • len , 表示列数据的长度;
  • type,表示列数据的类型 。
物理记录由 rec_t 数据结构表示 , 字节类型 。
/* We define the physical record simply as an array of bytes */typedef byte rec_t;页概念页和记录类似同样可以分为以下两种形式:
  • 物理页(block),表示存储在外部存储设备上,一般是持久的 。block 是文件系统中一次 IO 的大?。?/li>
  • 内存页(page) , 表示存储在缓冲池(buffer pool)中,当物理页与内存页不同时表明是脏页 。
页分多种类型,比如 index page、undo log page 等,本文关注的是 index page 。
由于 InnoDB 是索引组织树,索引即数据,因此可以将索引页理解为数据页 。
InnoDB 中页是一个无序堆,因此页中的记录无序存放,记录间通过 record header 中的 next record 组成单向链表 。
数据结构buffer pool 中与页相关的有两个数据结构,包括 buf_block_t 和 buf_page_t。
buf_block_t 是数据页控制体的一种 。
/** The buffer control block structure */struct buf_block_t{ buf_page_t page;/*!< page information; this mustbe the first field, so thatbuf_pool->page_hash can pointto buf_page_t or buf_block_t */ byte*frame; BPageLock lock;/*!< read-write lock of the buffer frame */


推荐阅读