MySQL是一个开源的关系型数据库管理系统,其性能高、成本低、可靠性好,加之web应用的兴起,现今已成为最流行的开源数据库之一。
在对MySQL系列专栏学习之前,首先要介绍一下MySQL的整体架构。
- Connection Pool(连接池):用于缓存建立的连接,为提升MySQL服务器的性能,尽可能的减少建立连接时的消耗。
- SQL Interface(SQL接口):接收客户端的SQL命令,并返回用户查询结果。
- Parser(解析器):对SQL进行语法校验,然后将SQL分解成相应的数据结构。
- Optimizer(优化器):优化客户端提交的SQL语句,以此来达到最佳的执行效率。
- Caches&Buffers(缓存器):查询缓存,可以加速查询。
- Pluggable Storege Engines(存储引擎):MySQL在5.1版本采用了插件式的架构,所有的存储引擎以插件的形式加载,我们常用的存储引擎如InnoDB。
- File System(File & Logs)(文件系统):索引、数据、表结构等的物理存储区。
下面我们就围绕MySQL最常用的存储引擎InnoDB展开讲解。
InnoDB存储引擎
InnoDB是MySQL的的一个常用存储引擎,是第一个完整支持ACID事务的存储引擎,其具有行锁设计,支持MVCC、支持外键、支持一致性非锁定等能力。
InnoDB存储引擎包含两大重要结构:内存池与文件系统,如下图是该存储引擎的整体架构:
- Background Threads(后台线程):后台线程的作用是负责刷新内存池中的数据,保证其新鲜度;同时也会将修改的数据刷新到对应磁盘文件中。
- Buffer Pool(内存缓冲池):内存缓冲池是一块很大的内存快,用于存放各种缓存数据,该区域的数据是以页(没页16K)为单位存储的,InnoDB会将文件中的数据读取存放到这里;同时所有的数据修改都是先修改缓冲池中的页,然后由后台线程定期将脏页(发生修改的页)刷新到磁盘文件中。
- 文件系统:这里存放的是物理数据文件,包含了表结构文件、索引文件、数据文件、临时缓存文件、日志文件等。
- InnoDB有三大特性:内存缓冲池、插入缓冲区、自适应哈希索引。
后台线程
InnoDB存储引擎至少包含7个后台线程:1个master thread(主线程)、1个lock thread(锁监视线程)、1个monitor thread(错误监视线程)以及4个IO thread,IO线程分别为insert buffer thread(管理插入缓冲区线程)、log thread(管理日志缓冲区的线程)、read thread和write thread。
内存池
InnoDB存储引擎内存由:buffer pool(缓冲池)、redo log buffer(重做日志缓冲池)及additional memory pool(额外内存池)组成,其中缓冲池是最大的一部分。
- buffer pool(缓冲池)由N个buffer page(缓冲页)构成,每个缓冲页的大小为16K(如上图中小方块)。缓冲池中又含量了多种数据页类型:index page(索引页)、data page(数据页)、undo page(undo页)、insert buffer(插入缓冲区)、adaptive hash index(自适应哈希索引)、lock info(多信息)及data dictionary(数据字典信息)等。
- redo log buffer(redo日常缓冲)是重做日志写入缓冲区,后续的后台线程会将日志刷到重做日志文件。
- additional memory pool(额外内存池)用于存放缓冲控制对象需要的LRU、锁、等待信息。
插入缓冲
存储引擎性能的最大影响因素是随机IO,插入聚集索引一般是顺序插入(id是递增的),不需要随机读写,所以没有此问题。然而非聚集索引读写是离散的(B+树结构),为保证非聚集索引的插入性能而设计。
若需要插入的索引页在缓冲池中,则直接插入,不在则会将其放入插入缓存,缓存区中同索引页的数据还会合并,然后再刷新到索引文件。
自适应哈希索引
根据当前视图的数据访问频次在缓冲池建立一个hash索引,这是一个自适应的辅助索引,该自适应hash索引值适用于等值查询。
文件系统
InnoDB磁盘中的结构分为几类:表空间、Redo Log、Doublewrite Buffer、Undo log。
- 表空间:分为System Tablespace(系统表空间)、Temporary Tablespaces(临时表空间)、General Tablespaces(常规表空间)、Undo Tablespaces(Undo表空间)以及file-per-table表空间,系统表空间包括Change Buffer。
- Redo log:存储的是log buffer刷到磁盘的数据,重做日志文件组内的文件会循环使用。
- Doublewrite buffer:InnoDB将数据页写到文件之前存放的位置。
- Undo log:存在于global临时表空间中,用于事务的回滚。
- frm:表结构定义文件。
我们重点介绍一下表空间结构。
表空间文件结构
表空间是InnoDB存储引擎逻辑结构的最高层,所有的数据都是存放在表空间中。InnoDB默认有一个共享表空间ibdata1,如果我们开启了file_per_table,则每张表内数据可以单独存放到一个表空间(注:每张表的数据、索引和插入缓冲存放在单独表空间,其它类型数据,如Undo log、Ddouble write buffer等仍然在共享表空间)。
具体表空间结构如下:
- Segment(段):表空间就是由N个段组成的,包括数据段、索引段、回滚段等。InnoDB的数据段时由B+树组织的,所有的数据段都是叶子节点,同时这些叶子节点在磁盘上都是连续的。而索引段都是非叶子节点,回滚段则用于事务回滚和多版本控制。每个段又包含256个区,占用256M。
- Extent(区):区是有64个连续的页组成的,每个页大小为16K,组成的区大小为1M。
- Page(页):页是InnoDB存储的最基本单位,因为其是InnoDB磁盘管理的最小单位。每页的大小为16K(操作系统磁盘分页大小为4K,这里会引入一个问题,后续我会在《InnoDB Double Write技术》详细讲解)。常见的页类型有:数据页、Undo页、系统页、事务数据页、插入缓冲位图页等。
- Row(行):InnoDB存储引擎是面向行的(注:也有面向列的数据库,例如ClickHouse),也就是说数据的存放按行进行存放的。每个页存放的行在7992行内。
行结构
InnoDB存储引擎与主流的关系型数据库的意义,记录是以行的形式存储的。InnoDB提供了Compact和Redundant两种格式来存放行记录数据,Redundant是一个历史结构兼容格式,我们主要介绍Compact格式。
Compact格式是MySQL5.0引入的,其结构如下:
- 首部是所有列的长度列表(逆序存放),当列的长度小于255字节时,其长度为1字节,否则用2字节表示,其最大值不超过2字节(注:这也就是为什么varchar最大长度为65535即2^16的原因),我们举个例子:
某行记录有三个字段分别是column1/column2/column3,其值分别为aaaa/b/cc,那么长度列表则为02 01 04
- NULL标志位,该标志位指示了该行是否有NULL值,有则为1。
- 记录头信息,固定占用5个字节,其中包含deleted_flag(删除标记)、记录在页堆中的相对位置信息、下一个记录的相对位置等信息。
- 每一行还包含两个隐藏列,事务ID列(6字节)和回滚指针列(7字节)。
- 若表没有定义Primary Key,则会增加一个RowID列(6字节)。
页结构
InnoDB数据页由七个部分组成,其中File Header、Oage Header、File Trailer、Infimun&Supremun Records4个是固定大小的,具体结构如下:
- File Header(文件头):38字节,其中包含了页的校验和、页类型、页序号、页在表空间的偏移量、前后页的指针、LSN等信息。
- Page Header(页头部信息):56字节,其中包含业内的记录数、Free Space在页面中的地址偏移、页目录槽数等信息。
- Infimun+Supremun Records:26字节,每个页都有这两个虚拟的行记录。用来限定页内记录的边界,Infimun页面中的最小记录,Supremun最大记录。
- User Records(用户记录):实际存储用户行记录的地方。
- Free Space(页的空闲空间):该区域则是待分配的空闲区域,有新的记录插入时则在该区域分配。
- Page Directory(页目录):这是一个稀疏目录,记录的是记录的分组信息(每组4-8个记录),每个槽指向分组记录的开始。查询记录时可以使用这个目录二叉查找快速定位记录所在的组,然后通过记录的next_recored指针,快速的获取到要查询的记录(注:这个查找与B+树的搜索不同,B+树是在内存中对页的组织,通过B+树找到页,在通过页目录定位到记录所在组,组内在用next_record指针查找)。
- File Trailer(文件结尾):8字节,保证页的完整性,检查其校验和、LSN值与File Header的校验和,即LSN值是否一致,不一致就说明发生了磁盘损坏或者宕机保存数据不完整等情况。
至此整个InnoDB的核心结构剖析完成。
总结
- MySQL包含连接池、SQL接口、解析器、优化器、缓存器、存储引擎、文件系统。
- InnoDB有三大特性:内存缓冲池、插入缓冲区、自适应哈希索引。
- InnoDB磁盘中的结构分为几类:表空间、Redo Log、Doublewrite Buffer、Undo log。
- InnoDB表空间结构分为:段、区、页、行。
- InnoDB页结构包含:文件头、页头部信息、Infimun+Supremun记录、用户记录、页的空闲空间、页目录、文件结尾。
- InnoDB行结构包含:变长字段长度列表、NULL标志位、记录头信息、RowID、事务ID、回滚指针、列数据。
《MySQL系列专栏》持续更新中,关注我不迷路[送心]。