常言说得好,每一个成功男人背后都有一个为他默默付出的女人,而对于MySQL来讲,这个“人”就是InnoDB存储引擎。数据库
MySQL区别于其余数据库的最为重要的特色就是其插件式的表存储引擎。而在众多存储引擎中,InnoDB是最为经常使用的存储引擎。从MySQL5.5.8版本开始,InnoDB存储引擎是默认的存储引擎。缓存
InnoDB存储引擎支持事务,其设计目标主要面向在线事务处理(OLTP)的应用。其特色是行锁设计、支持外键,并支持非锁定读,即默认读操做不会产生锁。微信
InnoDB经过使用多版本并发控制(MVCC)来获取高并发性,而且实现了SQL标准的4中隔离级别,默认为REPEATABLE级别。同时,使用一种被称为next-key-locking的策略来避免幻读现象的产生。除此以外,InnoDB存储引擎还提供了插入缓冲(insert buffer)、二次写(double write)、自适应哈希索引(adaptive hash index)、预读(read ahead)等高性能和高可用的功能。架构
InnoDB存储引擎是基于磁盘存储的,并将其中的记录按照页的方式进行管理。可是因为CPU速度和磁盘速度之间的鸿沟,基于磁盘的数据库系统一般使用缓冲池记录来提升数据库的的总体性能。并发
在数据库中进行读取操做,首先将从磁盘中读到的页放在缓冲池中,下次再读相同的页中时,首先判断该页是否在缓冲池中。若在缓冲池中,称该页在缓冲池中被命中,直接读取该页。不然,读取磁盘上的页。函数
对于数据库中页的修改操做,则首先修改在缓冲池中的页,而后再以必定的频率刷新到磁盘上。页从缓冲池刷新回磁盘的操做并非在每次页发生更新时触发,而是经过一种称为CheckPoint的机制刷新回磁盘。高并发
因此,缓冲池的大小直接影响着数据库的总体性能,能够经过配置参数innodb_buffer_pool_size来设置。性能
具体来看,缓冲池中缓存的数据页类型有:索引页、数据页、undo页、插入缓冲(insert buffer)、自适应哈希索引(adaptive hash index)、InnoDB存储的锁信息(lock info)和数据字典信息(data dictionary)。学习
在架构图上能够看到,InnoDB存储引擎的内存区域除了有缓冲池以外,还有重作日志缓冲和额外内存池。InnoDB存储引擎首先将重作日志信息先放到这个缓冲区中,而后按照必定频率将其刷新到重作日志文件中。重作日志缓冲通常不须要设置的很大,该值可由配置参数innodb_log_buffer_size控制。优化
Page是Innodb存储的最基本结构,也是Innodb磁盘管理的最小单位,与数据库相关的全部内容都存储在Page结构里。Page分为几种类型,数据页和索引页就是其中最为重要的两种类型。
咱们都知道,在InnoDB引擎上进行插入操做时,通常须要按照主键顺序进行插入,这样才能得到较高的插入性能。当一张表中存在非聚簇的且不惟一的索引时,在插入时,数据页的存放仍是按照主键进行顺序存放,可是对于非聚簇索引叶节点的插入再也不是顺序的了,这时就须要离散的访问非聚簇索引页,因为随机读取的存在致使插入操做性能降低。
InnoDB为此设计了Insert Buffer来进行插入优化。对于非聚簇索引的插入或者更新操做,不是每一次都直接插入到索引页中,而是先判断插入的非汇集索引是否在缓冲池中,若在,则直接插入;若不在,则先放入到一个Insert Buffer中。看似数据库这个非汇集的索引已经查到叶节点,而实际没有,这时存放在另一个位置。而后再以必定的频率和状况进行Insert Buffer和非聚簇索引页子节点的合并操做。这时一般可以将多个插入合并到一个操做中,这样就大大提升了对于非聚簇索引的插入性能。
若是说Insert Buffer给InnoDB存储引擎带来了性能上的提高,那么Double Write带给InnoDB存储引擎的是数据页的可靠性。
如上图所示,Double Write由两部分组成,一部分是内存中的double write buffer,大小为2MB,另外一部分是物理磁盘上共享表空间连续的128个页,大小也为2MB。在对缓冲池的脏页进行刷新时,并不直接写磁盘,而是经过memcpy函数将脏页先复制到内存中的该区域,以后经过doublewrite buffer再分两次,每次1MB顺序地写入共享表空间的物理磁盘上,而后立刻调用fsync函数,同步磁盘,避免操做系统缓冲写带来的问题。在完成doublewrite页的写入后,再讲doublewirite buffer中的页写入各个表空间文件中。
若是操做系统在将页写入磁盘的过程当中发生了崩溃,在恢复过程当中,InnoDB存储引擎能够从共享表空间中的doublewrite中找到该页的一个副本,将其复制到表空间文件中,再应用重作日志。
当缓冲池中的页的版本比磁盘要新时,数据库须要将新版本的页从缓冲池刷新到磁盘。可是若是每次一个页发送变化,就进行刷新,那么性能开发是很是大的,因而InnoDB采用了Write Ahead Log策略,即当事务提交时,先写重作日志,而后再择时将脏页写入磁盘。若是发生宕机致使数据丢失,就经过重作日志进行数据恢复。
InnoDB存储引擎会首先将重作日志信息先放入重作日志缓冲中,而后再按照必定频率将其刷新到重作日志文件。重作日志缓冲通常不须要设置得很大,由于通常状况每一秒钟都会讲重作日志缓冲刷新到日志文件中。可经过配置参数innodb_log_buffer_size控制,默认为8MB。
除了每秒刷新机制以外,每次事务提交时重作日志缓冲也会刷新到日志中。InnoDB是事务的存储引擎,其经过Force Log at Commit机制实现事务的持久性,即当事务提交时,必须先将该事务的全部日志写入到重作日志文件进行持久化,而后事务的提交操做完成才算完成。InnoDB的写入机制大体入下图所示。
为了确保每第二天志都写入到重作日志文件,在每次讲重作日志缓冲写入重作日志后,必须调用一次fsync操做,将缓冲文件从文件系统缓存中真正写入磁盘。
能够经过innodb_flush_log_at_trx_commit来控制重作日志刷新到磁盘的策略。该参数默认值为1,表示事务提交必须进行一次fsync操做,还能够设置为0和2。0表示事务提交时不进行写入重作日志操做,该操做只在主线程中完成,2表示提交时写入重作日志,可是只写入文件系统缓存,不进行fsync操做。因而可知,设置为0时,性能最高,可是丧失了事务的一致性。
InnoDB会根据访问的频率和模式,为热点页创建哈希索引,来提升查询效率。InnoDB存储引擎会监控对表上各个索引页的查询,若是观察到创建哈希索引能够带来速度上的提高,则创建哈希索引,因此叫作自适应哈希索引。
自适应哈希索引是经过缓冲池的B+树页构建而来,所以创建速度很快,并且不须要对整张数据表创建哈希索引。其有一个要求,即对这个页的连续访问模式必须是同样的,也就是说其查询的条件(WHERE)必须彻底同样,并且必须是连续的。
咱们都知道,InnoDB存储引擎会在行级别上对表数据进行上锁。不过InnoDB也会在数据库内部其余不少地方使用锁,从而容许对多种不一样资源提供并发访问。数据库系统使用锁是为了支持对共享资源进行并发访问,提供数据的完整性和一致性。关于锁的具体知识咱们以后再进行详细学习。
InnoDB有本身的表缓存,能够称为表定义缓存或者数据字典。当InnoDB打开一张表,就增长一个对应的对象到数据字典。
数据字典是对数据库中的数据、库对象、表对象等的元信息的集合。在MySQL中,数据字典信息内容就包括表结构、数据库名或表名、字段的数据类型、视图、索引、表字段信息、存储过程、触发器等内容。MySQL INFORMATION_SCHEMA库提供了对数据局元数据、统计信息、以及有关MySQL server的访问信息(例如:数据库名或表名,字段的数据类型和访问权限等)。该库中保存的信息也能够称为MySQL的数据字典。
本篇文章只是简单的介绍一下InnoDB内存相关的概念和原理,若是你们想要了解更多关于InnoDB的知识,请关注个人微信公众号。