Mysql-InnoDB引擎基础架构
InnoDB引擎基础架构
InnoDB引擎存储架构如下图,左侧为InnoDB引擎的内存架构,右侧为InnoDB引擎的磁盘架构

逻辑存储结构

- Tablespace(表空间):
一个Mysql实例可以对应多个表空间,用于存储记录、索引等数据。表空间在磁盘中存储为.ibd文件; - Segment(段):
分为数据段(Leaf node segment)、索引段(Non-leaf node segment)、回滚段(Rollback segment),InnoDB是索引组织表,数据段即是B+树的叶子结点,索引段即为B+树的非叶子结点。段用来管理多个Extent(区); - Extent(区):
表空间的单元结构,每个区的大小为1M。默认情况下,InnoDB存储引擎页大小为16K,即一个区中一共有64个连续页; - Page(页):
InnoDB存储引擎磁盘管理的最小单元,每个页的大小默认为16KB。为了保证页的连续性,InnoDB存储引擎每次从磁盘申请4~5个区; - Row(行):
InnoDB存储引擎数据是按行进行存放的;
①Trx_id:每次对某条记录进行改动时,都会把对应的事务id赋值给trx_id隐藏列;
② Roll_pointer:每次对某条记录进行改动时,都会把旧的版本写入undo日志中,然后Roll_point隐藏列就相当于一个指针,可以通过它找到该记录修改前的信息。
内存架构

- Buffer Pool(缓冲池):
缓冲池是主内存中的一块区域,里面可以缓存磁盘上经常操作的数据,在增删改查时,先操作Buffer Pool中的内存数据(如果缓冲池没有数据,则从磁盘中加载并缓存),再以一定频率将数据刷入磁盘中。这样做可以提高操作数据库数据的性能,减少磁盘IO消耗;
缓冲池以Page为单位,底层采用链表的结构管理Page。根据状态,将Page分为三类:
① free page:空闲page,未被使用;
② clean page:被使用的page,数据未被修改过;
③dirty page:脏页,被使用page,数据被修改过,页中的数据与磁盘数据产生了不一致。 - Change Buffer(更改缓冲区):
对于非唯一二级索引,在执行DML语句时,如果该数据不在Buffer Pool中,InnoDB会将它的数据变更存入Change Buffer中,在未来数据被读取时,再将数据合并回复到Buffer Pool中,按照Buffer Pool的机制再将合并后的数据刷入磁盘中。 -
- 问题:
为什么是非唯一二级索引?为什么Change Buffer不为聚集索引和唯一二级索引服务?
- 问题:
-
- 答案:
①聚集索引:聚集索引决定了数据在磁盘上的物理存储顺序,所以在执行DML语句时,需要直接修改磁盘上的数据页和索引页,相关的所有二级索引都需要更新。
如不立即写入,那么二级索引的更新会存在滞后,导致聚集索引和二级索引不一致,可能会导致查询结果异常或数据完整性受到威胁。
相比之下非唯一二级索引并不涉及对数据物理存储顺序的更改,它只关注特定列上的值和对应数据行的位置关系,因此非唯一二级索引的修改可以先计入缓冲区,稍后写入磁盘,不会影响数据的物理存储顺序和其它二级索引的一致性。
②唯一二级索引:对于唯一二级索引的修改操作,InnoDB引擎需要在操作数据时立即检查唯一性约束,以确保索引的唯一性,因此无法延迟数据的修改。
- 答案:
- Adaptive Hash Index(自适应哈希索引):
用于优化对Buffer Pool数据的查询,InnoDB引擎会监控表上各索引页的查询,如果观察到hash索引可以提高检索速度,则建立hash索引。自适应哈希索引无需人工构建,是系统根据情况自动完成;
查看自适应哈希索引情况:SHOW VARIABLES LIKE '%hash_index%'

- Log Buffer(日志缓冲区):
用来保存要写入到磁盘中的log日志数据(redo log、undo log),缓冲区默认大小为16MB。缓冲区数据会按一定策略写入磁盘中。
写入磁盘的策略有二:
①在每次事务提交时写入缓冲区并刷新到磁盘;
②日志在每次事务提交后写入缓冲区,每秒钟刷新到磁盘一次。
查看日志缓冲区大小:SHOW VARIABLES LIKE 'innodb_log_buffer_size'

磁盘架构

- System Tablespace(系统表空间):
是更改缓冲区的存储区域,如果表是在系统表空间而不是每个表文件或者通用表空间中创建的,它也可能包含表和索引数据。(在Mysql5.x版本中还包含InnoDB数据字典、undolog等); - File-Per-Table Tablespaces:
每个表的文件表空间包含单个InnoDB表的数据和索引,并存储在文件系统上的单个数据文件中。参数:innodb_file_per_table,如果value为ON,则每张表都会生成一个对应的表空间文件。

- General Tablespaces(通用表空间):
需要通过CREATE TABLESPACE 语法创建通用表空间,在创建表时,可以指定该表空间。
创建表空间:CREATE TABLESPACE XXX ADD DATAFILE 'file_name' ENGINE = engine_name;
创建表时指定表空间:CREATE TABLE xxx TABLESPACE xxx - Undo Tablespaces(撤销表空间):
Mysql实例在初始化时会自动创建两个默认的undo表空间(初始大小16M),用于存储undo log日志; - Temporary Tablespaces(临时表空间):
InooDB使用临时表空间和全局临时表空间存储用户创建的临时表数据。 - Doublewrite Buffer Files【重要】:
双写缓冲区,InnoDB引擎将数据页从Buffer Pool刷新到磁盘前,先将数据页写入双写缓冲区文件中,便于系统异常时回复数据。

- Redo Log(重做日志)【重要】:
用来实现事务的持久性。该日志文件由两部分组成:重做日志缓冲(redo log buffer)和 重做日志文件(redo log),前者在于内存中,后者在磁盘中。当事务提交后会把所有修改信息都存到该日志中,用于在刷新脏页到磁盘发生错误时进行数据恢复。
后台线程

InooDB引擎存在大量不同职能的后台线程,共同完成数据操作、持久化等工作。
- Master Thread
核心后台线程,负责调度其他线程,还负责将缓冲池中的数据异步刷新到磁盘中,保持数据的一致性,还包括脏页的刷新、合并插入缓存、undo页的回收; - IO Thread
在InnoDB引擎中使用大量AIO(异步非阻塞IO)来处理IO请求,可以极大地提高数据库性能。而IO Thread 主要负责这些IO请求的回调。

- Purge Thread
主要用于回收事务已经提交了的undo log,在事务提交后,undo log 可能不用了,就用它来回收; - Page Cleaner Thread
协助 Master Thread 刷新脏页到磁盘的线程,可以减轻 Master Thread 的工作压力,减少阻塞。
InnoDB引擎的存储结构包括表空间、段、区、页和行,其中缓冲池是内存中的关键部分,用于缓存数据以减少磁盘IO。更改缓冲区用于非唯一二级索引的修改,自适应哈希索引提供查询优化。磁盘架构涉及系统表空间、文件表空间、通用表空间等,重做日志确保事务的持久性。后台线程如MasterThread负责数据刷新和调度,IOThread处理IO请求,PurgeThread回收undolog。


被折叠的 条评论
为什么被折叠?



