前言
InnoDB体系架构
InnoDB主要包括了:内存池、后台线程以及存储文件。内存池又是由多个内存块组成的,主要包括缓存磁盘数据、redolog缓冲等;后台线程则包括了:MasterThread、IOThread以及PurgeThread等;由InnoDB存储引擎实现的表的存储结构文件一般包括表结构文件(.frm)、共享表空间文件(ibdata1)、独占表空间文件(ibd)以及日志文件(redo文件等)等。
1.内存池
我们知道,如果客户端从数据库中读取数据是直接从磁盘读取的话,无疑会带来一定的性能瓶颈,缓冲池的作用就是提高整个数据库的读写性能。
客户端读取数据时,如果数据存在于缓冲池中,客户端就会直接读取缓冲池中的数据,否则再去磁盘中读取;对于数据库中的修改数据,首先是修改在缓冲池中的数据,然后再通过MasterThread线程刷新到磁盘上。
理论上来说,缓冲池的内存越大越好。缓冲池中不仅缓存索引页和数据页,还包括了undo页,插入缓存、自适应哈希索引以及InnoDB地锁信息等等。
InnoDB允许多个缓冲池实例,从而减少数据库内部资源的竞争,增强数据库的并发处理能力,第38讲还讲到了缓冲池实例的配置以及调优。
InnoDB存储引擎会先将重做日志信息放入到缓冲区中,然后再刷新到重做日志文件中。
2.后台线程
MasterThread主要负责将缓冲池中的数据异步刷新到磁盘中,除此之外还包括插入缓存、undo页的回收等,IOThread是负责读写IO的线程,而PurgeThread主要用于回收事务已经提交了的undolog,PagerCleanerThread是新引入的一个用于协助MasterThread刷新脏页到磁盘的线程,它可以减轻MasterThread的工作压力,减少阻塞。
3.存储文件
在MySQL中建立一张表都会生成一个.frm文件,该文件是用来保存每个表的元数据信息的,主要包含表结构定义。
在InnoDB中,存储数据都是按表空间进行存放的,默认为共享表空间,存储的文件即为共享表空间文件(ibdata1)。若设置了参数innodb_file_per_table为1,则会将存储的数据、索引等信息单独存储在一个独占表空间,因此也会产生一个独占表空间文件(ibd)。如果你对共享表空间和独占表空间的理解还不够透彻,接下来我会详解。
而日志文件则主要是重做日志文件,主要记录事务产生的重做日志,保证事务的一致性。
InnoDB逻辑存储结构
InnoDB逻辑存储结构分为表空间(Tablespace)、段(Segment)、区(Extent)、页Page)以及行(row)。
1.表空间(Tablespace)
InnoDB提供了两种表空间存储数据的方式,一种是共享表空间,一种是独占表空间。InnoDB默认会将其所有的表数据存储在一个共享表空间中,即ibdata1。
我们可以通过设置innodb_file_per_table参数为1(1代表独占方式)开启独占表空间模式。开启之后,每个表都有自己独立的表空间物理文件,所有的数据以及索引都会存储在该文件中,这样方便备份以及恢复数据。
2.段(Segment)
表空间是由各个段组成的,段一般分为数据段、索引段和回滚段等。我们知道,InnoDB默认是基于B+树实现的数据存储。
这里的索引段则是指的B+树的非叶子节点,而数据段则是B+树的叶子节点。而回滚段则指的是回滚数据。
3.区(Extent)/页(Page)
区是表空间的单元结构,每个区的大小为1MB。而页是组成区的最小单元,页也是InnoDB存储引擎磁盘管理的最小单元,每个页的大小默认为16KB。为了保证页的连续性,InnoDB存储引擎每次从磁盘申请4-5个区。
4.行(Row)
InnoDB存储引擎是面向列的(row-oriented),也就是说数据是按行进行存放的,每个页存放的行记录也是有硬性定义的,最多允许存放16KB/2-行,即行记录。
InnoDB事务之redolog工作原理
InnoDB是一个事务性的存储引擎,而InnoDB的事务实现是基于事务日志redolog和undolog实现的。redolog是重做日志,提供再写入操作,实现事务的持久性;undolog是回滚日志,提供回滚操作,保证事务的一致性。
redolog又包括了内存中的日志缓冲(redologbuffer)以及保存在磁盘的重做日志文件(redologfile),前者存储在内存中,容易丢失,后者持久化在磁盘中,不会丢失。
InnoDB的更新操作采用的是WriteAheadLog策略,即先写日志,再写入磁盘。当一条记录更新时,InnoDB会先把记录写入到redologbuffer中,并更新内存数据。我们可以通过参数innodb_flush_log_at_trx_