前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >关系型数据库 MySQL 之 InnoDB 体系结构

关系型数据库 MySQL 之 InnoDB 体系结构

作者头像
JiekeXu之路
发布2019-08-15 15:10:36
1.3K0
发布2019-08-15 15:10:36
举报
文章被收录于专栏:JiekeXu之路JiekeXu之路

一、InnoDB 体系结构

InnoDB 存储引擎是 MySQL 5.5 版本后的默认存储引擎,支持事务 ACID,回滚,系统崩溃恢复能力及多版本并发控制的事务安全,主要用于 OLTP 数据库业务场景;支持自增长列(auto_increment);支持外键约束(foreign key);支持 MVCC 的行级锁;使用 Btree 索引;如果你还没有看到前面一文介绍 MySQL 体系结构,那么推荐戳此查看[MySQL 体系结构详解],介绍完 MySQL 体系结构,下面来一起学习 InnoDB 体系结构。

下图为 MySQL 5.7 官方手册下 InnoDB 体系结构,详情可见官方手册。

InnoDB存储引擎主要包括多个内存池以及后台线程。

内存池

内存池由 Buffer Pool 包括(undopage、Change buffer page、AdaptiveHash Index、Lock info、datadictionary),Double write Buffer,Additional Memory pool、Redo Log Buffer 组成,主要维护进程/线程的内部数据、缓存磁盘数据,修改文件前先在内存中修改;

MySQL5.7 官方文档中关于 InnoDB 存储引擎的体系结构讲解包括:

代码语言:javascript
复制
Buffer Pool
Change Buffer
Adaptive Hash Index
Redo Log Buffer
System Tablespace
InnoDB DataDictionary
Doublewrite Buffer
Undo Logs
File-Per-TableTablespaces
General Tablespaces
Undo Tablespace
Temporary Tablespace
Redo Log

共享表空间和独立表空间

InnoDB 有表空间的概念,包括共享表空间和独立表空间(独立表空间的模式中也要有系统表空间 ibdata1,来用于存储内部的数据字典、Undo日志等,通过 InnoDB_file_per_table 参数设置启用独立表空间),默认独立表空间模式下会在数据目录下创建 tablename.ibd、tablename.frm 文件,但如果单表增长过快这样就很容易出现性能问题。共享表空间的数据和文件放在一起方便管理,但共享表空间无法在线回收空间,若想要回收需要将全部的 InnoDB 表中的数据备份、删除原表,然后再把数据倒回到原表结构一样的新表中。

临时表空间和通用表空间

MySQL 5.7 把临时表的数据从系统表空间中抽离出来,形成自己的独立的表空间参数innodb_temp_data_file_path, 并且把临时表的相关检索信息保存在系统信息表的 information_schema 库下的 innodb_temp_table_info 表中。但目前还不能定义临时表空间文件的存放路径,只能和 innodb_data_home_dir 一致。临时表空间命名为 ibtmp1,默认大小为 12 M。

通用表空间就是将多个表放置在同一个表空间中,可以根据 活跃度来划分表,存在不同的磁盘上,可减少 metadata 的存储开销,但很少在生产环境中使用。

redo

InnoDB 支持记录 Redo文件,记录对所有页面的修改(页面物理结构的变更)操作,可以通过相关的参数进行自定义设置 Redo文件存储路径。

undo

InnoDB 支持记录 Undo 文件,记录数据修改前的备份,存储在共享表空间中。用户保证事务的原子性(恢复)和实现 MVCC 多版本并发控制,辅助完成事务的持久化(Undo 信息会持久化)。可通过相关参数进行自定义设置。

更改缓冲

更改缓冲(change buffer),基于聚集索引的操作是顺序的,不会造成数据库随机读取,但修改非聚集索引时就会产生大量的随机读写。当修改非聚集索引的数据时,修改操作并非实时更新索引的叶子页,而是把若干对同一页面的更新缓存起来做合并(merge)将一次性更新操作,转化随机 IO 为顺序 IO ,这样可以避免随机 IO 带来性能损耗,提高数据库的写性能。

两次写

两次写(double write),(重做日志记录的是页的物理操作,如果页本身损坏,对其重做就没有意义了,在应用重做日志前,需要一个页的副本。

先通过页的副本还原该页,再应用重做日志进行恢复)当 MySQL 将脏数据 flush 到 data file 的时候,先使用memcopy 将脏数据复制到内存中的double write buffer,之后通过double wirte buffer 再分 2 次,每次写入 1M 到共享表空间,然后马上调用 fsync 函数,同步到磁盘上;

将数据页(page)加载到内存(InnoDB buffer)->更新数据产生脏页(dirty page)->使用 memcopy 将脏数据复制到内存中的double write buffer(size=2M)->double wirte buffer 再分2次,每次写入1 M 到共享表空间(ibdata 文件)->调用 fsync 函数,同步到磁盘;

使用memcopy将脏数据复制到内存中的double write buffer(size=2M)->double wirte buffer 再分 2 次,每次写入 1M 到共享表空间(ibdata 文件)就是 double 的过程。

自适应 hash 索引

自适应 hash 索引(adaptive hash index),InnoDB 会监控表上索引的查找情况,如果通过建立 Hash 索引能带来性能的提升,则会自动建立 hash 索引,该过程只能由MySQL Server 自行控制,无法人工干预且只适用于等值索引查询;从 MySQL 5.7.8 开始,自适应哈希索引搜索系统是分区的,每个索引都会绑定到一个特殊的分区上面,且各个分区都有自己的锁存器来进行保护。

分区可以通过 InnoDB_adaptive_hash_index_parts 参数来控制,该参数的默认值为 8 个,最大可设置为 512。通过设置分区值,可以降低争用,提高并发性。还可以通过命令 SHOW ENGINE INNODB STATUS 所输出的 SEMAPHORES 部分来监控自适应哈希索引的使用及其竞争情况。如果你看到许多线程正在等待一个在 btr0sea.c 中创建的 RW-latch,则它可能被用于禁用自适应哈希索引。

后台线程

后台线程包括(Mater Thread、IOThread、Lock Monitor Thread、ErrorMonitor Thread、Purge Thread、PageCleaner Thread)刷新内存池中的过程数据,管理维护 InnoDB 存储引擎正常工作。

InnoDB 主要的后台线程如下图。

Master Thread 是一个非常核心的后台线程,主要负责将缓冲池中的数据异步刷新到磁盘,保证数据的一致性,包括:脏页(dirty page)的刷新、合并插入缓冲(insert buffer merge)、回滚页回收(undo purge)等。innodb_max_dirty_pages_pct 脏页刷盘的配置参数,新版默认 75。

二、InnoDB 表逻辑结构

InnoDB 逻辑存储单元主要分为表空间、段、区和页,层级关系为tablespace——>segment——>extent(64 个 page, 1MB )——>page(默认 16K)。

表空间

表空间是 InnoDB 存储引擎逻辑结构的最高层,所有的数据都是存储在表空间中的,表空间又可以分为系统表空间、独立表空间。MySQL 5.7 之后从系统表空间中抽离出来了临时表空间(temporarytablespace)、通用表空间(general tablespace)。

,表空间是由段组成可以把表理解为一个段,又数据段,索引段,回滚段等。每个段又由 N 个区和 32 个零散的页组成,段空间扩展是以区为单位进行扩展的。

,由 64 个连续的页组成,是物理上连续分配的一段空间,每个区固定大小 1MB。

,InnoDB 的最小物理存储分配单位是 page,每个页 16KB 且不能修改,数据页,索引页,系统页等。

,页里面记录着行记录的信息, InnoDB 存储引擎是面向行的,也就是数据是按行存储的,每页最多允许存放 7992 行数据。

行记录格式

InnoDB 存储引擎有两种文件格式,一种叫 Antelope,另一种叫 Barracuda。在 Antelope 文件格式下,有 compact 和 redundant 两种行记录格式,而在 Barracuda 文件格式下,有 compressed 和 dynamic 两种行记录格式。

对于 Compact,不管是 char 型还是 varcha r型,null 型都是不占用存储空间的;对于Redundant,varchar 的 null 不占用空间,char 的 nul l型是占用存储空间的。

Varchar 类型的长度是 65535 ,但实际一般除开其他开销大概 65530 左右,同时这个限制是一整行数据的长度。

代码语言:javascript
复制
create tabletbl_varchar(
a varchar(22000), b varchar(22000), c varchar(22000)
)
charset=latin1 engine=innodb;   #会报错,因为一行总长大于了65535

数据页结构

File Header(文件头):记录页的头信息,固定长度 38 字节;

Page Header(页头):记录页的状态信息,固定长度 65 字节;

Infimum+SupremumRecords:两个虚拟的行记录,用于限定记录的边界;

User Records:用户记录,实际记录的内容,InnoDB 采用 B+ 树索引组织存储表;

Free Space:空闲空间,链表数据结构,记录删除后会被加入空闲空间;

Page Director:页目录,存放记录的相对位置,B+ 索引不能找到具体的一条记录,只能找到该记录所在的页,数据库把页载入内存,再通过 PageDirector 查找具体记录行;

File Trailer:文件结尾信息,固定长度 8 字节;

三、内存结构

MySQL 的内存结构和 Oracle 内存结构相似,也可分为 SGA(系统全局区)和 PGA(系统全局区),数据库的内存参数配置可以使用 [show variables like ‘%buffer%’] 命令查看。

内存主要由以下部分组成,由于篇幅具体每个功能暂时不做介绍,后期有机会在说。

注意:temp_table_size 和 max_heap_table_size 大小设置成一致,如果不一致,则会按照最小的来起作用,但也不要太小,否则会报错。

四、SQL 查询全过程

如下图所示,SQL 查询结果的全过程。

查询缓存,判断 SQL 语句是否完全匹配,再判断是否有权限,两个判断为假则到解析器解析语句,为真则提取数据结果返回给用户;

解析器解析:解析器先词法分析,语法分析,检查错误比如引号有没闭合等,然后生成解析树;

预处理:预处理解决解析器无法决解的语义,如检查表和列是否存在,别名是否有错,生成新的解析树;

优化器做大量的优化操作;生成执行计划;

查询执行引擎,负责调度存储引擎获取相应数据;返回结果。


参考资料

https://my.oschina.net/peakfang/blog/2240253

https://dev.mysql.com/doc/refman/5.7/en/innodb-storage-engine.html

张甦 著 《MySQL王者晋级之路》

注:全文均参考以上资料,如侵权联系可及时删除,若想获取更多,可访问以上链接。

本文参与 腾讯云自媒体分享计划,分享自微信公众号。
原始发表:2019-03-07,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 JiekeXu之路 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 一、InnoDB 体系结构
  • 二、InnoDB 表逻辑结构
  • 三、内存结构
  • 四、SQL 查询全过程
  • 参考资料
相关产品与服务
云数据库 SQL Server
腾讯云数据库 SQL Server (TencentDB for SQL Server)是业界最常用的商用数据库之一,对基于 Windows 架构的应用程序具有完美的支持。TencentDB for SQL Server 拥有微软正版授权,可持续为用户提供最新的功能,避免未授权使用软件的风险。具有即开即用、稳定可靠、安全运行、弹性扩缩等特点。
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档