该存储引擎是第一个完整支持ACID事务的MySQL存储引擎。
ACID:原子性、一致性、隔离性、持久性
一、InnoDB体系结构
1.PNG
InnoDB存储引擎有很多内存块,这些内存块组成了一个大的内存池,负责如下工作:
①维护所有进程、线程需要访问的多个内部数据结构。
②缓存磁盘上的数据,方便快速的读取,同时在对磁盘文件的数据修改之前在这里缓存。
③重做日志缓冲。
*:后台线程的主要作用是负责刷新内存池中的数据,保证缓冲池中的内存缓存的是最近的数据,此外将已经修改的数据文件刷新到磁盘文件,同时保证在数据库发生异常的情况下InnoDB能恢复到正常运行状态。
(一)后台线程
InnoDB存储引擎是多线程的模型,因此其后台会有多个不同的后台进程。
①Master Thread:
主要负责将缓冲池中的数据异步刷新到磁盘,保证数据的一致性,包括脏页的刷新、合并插入缓冲、UNDO页回收等。
②IO Thread:
在InnoDB存储引擎中大量使用了AIO来处理写IO请求,这样极大的提高了数据库的性能,而IO Thread 的工作主要是负责这些IO请求的回调处理。
③Purge Thread(净化线程):
作用在于回收已经使用并分配的undo页,从InnoDB1.1版本开始,purge操作可以独立到单独的线程中进行,以此来减轻Master Thread 的工作,从而提高CPU的使用率以及提升存储引擎的性能,用户可以在MySQL数据的配置文件中添加如下命令来启动独立的Purge Thread:
【mysqld】
innodb_purge_threads=1
从InnoDB 1.2开始,支持多个Purge Thread,这样做的目的能够加快undo页的回收,同时也能利用磁盘的随机读取性能。
④Page Cleaner Thread:
其作用是将之前版本中脏页的刷新操作都放入到单独的线程中来完成。而其目的是为了减轻原Master Thread 的工作以及对于用户查询线程的阻塞,进一步提高InnoDB存储引擎的性能。
(二)内存
①缓冲池
InnoDB存储引擎是基于磁盘存储的,并将其中的记录按照页的方式进行管理。基于磁盘的数据库系统通常是使用缓冲池来提高数据库的整体性能。
缓冲池简单来说就是一块内存区域,通过内存的速度来弥补磁盘速度较慢对数据库性能的影响。
比如:
在数据库中进行读取页的操作,首先将从磁盘读到的页存放在缓冲池中,这个过程叫作将页“FIX”在缓冲池下,下一次读取相同的页时候,首先判断该页是否在缓冲池中,若再缓冲池中,直接读取,否则,读取磁盘。
而对于修改操作,就是先修改缓冲池上的,再刷新到磁盘。
所以缓冲池的大小直接影响着数据库的整体性能,其缓冲池的配置可以通过参数:innodb_buffer_pool_size来设置。
从InnoDB 1.0.x开始,允许有多个缓冲池实例(可以通过innodb_buffer_pool_instancees),每个页根据哈希值平均分配到不同的缓冲池实例中。这样做的好处是减少数据库内部的资源竞争,增加数据库的并发处理能力。
②LRU List 、Free List、Flush List
缓冲池是一个很大的内存区域,其中存放了各种类型的页,那么InnoDB存储引擎是怎么对这么大的内存区域进行管理的呢?
答:
通常来说,数据库中缓冲池是通过LRU算法来进行管理的,即最频繁使用的页在LRU列表的前端,而最少使用的页在LRU列表的尾端。当缓冲池不能存放新读取到的页时,将首先释放LRU列表中尾端的页。
在InnoDB存储引擎中,缓冲池大小默认为16kb,同样使用LRU算法对缓冲池进行管理,稍有不同的是InnoDB存储引擎对传统的LRU算法做了一些优化。也就是:新读取到的页不是直接放在首部(某些SQL操作可能会使缓冲池中的页被刷新出,从而影响缓冲池的效率),而是放到LRU列表的midpoint位置,这个位置可以由参数innodb_old_blocks_pct控制。
③重做日志缓冲
InnoDB存储引擎首先将重做日志信息先放入到这个缓冲区,然后按一定频率将其刷新到重做日志文件。重做日志文件缓冲一般不需要设置的很大, 因为一般情况下每一秒钟会将重做日志缓冲刷新到日志文件,因此用户只需要保证每秒产生的事务量在这个缓冲大小之内就可以了,这个值由innodb_log_buffer_size控制,默认8MB:
通常情况下8MB就够了,原因在于重做日志在一些情况下会将重做日志缓冲中的内容刷新到外部磁盘的重做日志文件中。
④额外的内存池
在InnoDB存储引擎中,对内存的管理是通过一种称为内存堆的方式进行的。在对一些数据本 身的内存进行分配时,就需要从额外的内存池中申请,当该内存不够时,会从缓冲池中进行申请。因此,在申请了很大的InnoDB缓冲池时,也应该考虑相应的增加这个值。
二、Checkpoint技术
目的是解决以下几个问题:
①缩短数据库的恢复时间
②缓冲池不够用时,将脏页刷新到磁盘;
③重做日志不可用时,刷新脏页。
三、Master Thread 工作方式
InnoDB存储引擎的主要工作都是在一个单独的后台线程Master Thread中完成的。
四、InnoDB的工作方式
InnoDB的存储引擎的关键特性包括:
①插入缓冲
-----------对于非聚合集索引的插入或者更新操作,不是每一次直接插入到索引也中,而是先判断插入的非聚合集索引是否在缓冲池中,若再则直接插入,若不在,则先放入到一个Insert Buffer对象中。数据库这个非聚集的索引已经插入到叶子节点,而实际并没有,只是存放在另一个位置。然后再以一定的频率和情况进行插入缓冲和辅助索引页子节点的合并操作,这时通常能将多个插入合并到一个操作中(因为在一个索引页中),这就大大提高了对于非聚集索引插入的性能。
②两次写
-----------doubleWrite由两个部分组成:内存中的double Write Buffer ,大小为2MB,和物理磁盘上共享的表空间中连续的128个页,大小也为2MB。
-----------在对缓冲池的脏页进行刷新时,并不直接写入磁盘,而是通过memcpy函数将脏页复制到内存中的double Write Buffer,之后通过double Write Buffer 再分两次,每次以1MB顺序地写入共享表空间的物理磁盘上,然后马上用fsync函数,同步磁盘,避免缓冲写带来的问题。
-----------如果操作系统在讲页写入磁盘的过程中发生了崩溃,在恢复过程中,存储引擎可以从共享表空间中的double Write 中找到该页的副本,将其复制到表空间文件,再应用重做日志。
③自适应哈希索引
-----------InnoDB存储引擎会监控对表上各索引页的查询,如果观察到建立哈希索引可以带来速度提升,则建立哈希索引。
④异步IO
-----------有两个重要的优势:可以多IO,也可以合并IO ,是当前数据库系统都采用的方式来处理磁盘操作。
⑤刷新邻接页
-----------当刷新一个脏页时,InnoDB存储引擎会检测该页所在区的所有页,如果是脏页,那么一起进行刷新,这样做的好处在于通过AIO可以将多个IO写入操作合并为一个IO操作,这在传统机械硬盘下有着显著优势,固态硬盘下不支持。
五、InnoDB存储引擎文件
(一)表空间文件:
1、InnoDB采用将存储的数据按表空间进行存放的设计。在默认配置下会有一个初始大小为10MB,名为idbdata1的文件(该文件是共用表空间),该文件就是默认的表空间文件
2、设置innodb_data_file_path参数后,所有基于InnoDB存储引擎的表的数据都会记录到该共享表空间中。
3、若设置了参数innodb_file_per_table,则用户可以将每个基于InnoDB存储引擎的表产生一个独立表空间。
4、独立表空间的命名规则为:表名.ibd。通过这样的方式,用户不用将所有数据都存放在默认的表空间中。
5、需要注意的是,这些单独的表空间文件,仅存储该表的数据、索引和插入缓冲BITMAP等信息,其余信息还是存放在默认的表空间。
(二)重做日志文件:
1、默认情况下,在InnoDB存储引擎的数据目录下会有两个名为ib_logfile0和ib_logfile1的文件。
2、在MySQL官方手册中将其称为InnoDB存储引擎的日志文件,不过更准确的定义应该是重做日志文件(redo log file)为什么强调是重做日志文件呢?
:因为重做日志文件对于InnoDB存储引擎至关重要,它们记录了对于InnoDB存储引擎的事务日志.
3、重做日志文件不能设置的太大,如果设置得很大,在恢复时可能需要很长时间,另一方面又不能设置得太小,否则可能导致一个事务的日志需要多次切换重做日志文件。
4、此外重做日志文件太小会导致频繁地发生async checkpoint,导致性能的抖动。
5、重做日志和二进制日志的不同点
:二进制日志会记录所有与MySQL数据库有关的日志记录,包括InnoDB、MyISAM,Heap等其他存储引擎的日志。而InnoDB存储引擎的重做日志只记录有关该存储引擎本身的事务日志。二进制文件是逻辑日志。而InnoDB存储引擎的重做日志文件记录的是关于每个页的更改情况。
6、此外,写入的时间也不同,二进制日志文件仅在事务提交前进行提交,即只写磁盘一次,不论这时该事务多大。而在事务进行的过程中,却不断有重做日志被写入到重做日志文件中
网友评论