MySQL探秘(四):InnoDB的磁盘文件及落盘机制

 任何一个技术都有其底层的关键基础技术,这些关键技术颇有可能也是其余技术的关键技术,学习这些底层技术,就能够一通百通,让你很快的掌握其余技术。如何在磁盘上存储数据,如何使用日志文件保证数据不丢失以及如何落盘,不只是MySQL等数据库的关键技术,也是MQ消息队列或者其余中间件的关键技术之一。数据库

InnoDB总体架构
 上图详细显示了InnoDB存储引擎的体系架构,从图中可见,InnoDB存储引擎由内存池,后台线程和磁盘文件三大部分组成。接下来咱们就来简单了解一下磁盘文件相关的概念和原理。

 InnoDB的主要的磁盘文件主要分为三大块:一是系统表空间,二是用户表空间,三是redo日志文件和归档文件。二进制文件(binlog)等文件是MySQL Server层维护的文件,因此未列入InnoDB的磁盘文件中。缓存

系统表空间和用户表空间

 InnoDB系统表空间包含InnoDB数据字典(元数据以及相关对象)而且doublewrite buffer,change buffer,undo logs的存储区域。系统表空间也默认包含任何用户在系统表空间建立的表数据和索引数据。系统表空间是一个共享的表空间由于它是被多个表共享的安全

 系统表空间是由一个或者多个数据文件组成。默认状况下,1个初始大小为10MB,名为ibdata1的系统数据文件在MySQL的data目录下被建立。用户可使用innodb_data_file_path对数据文件的大小和数量进行配置。bash

 innodb_data_file_path的格式以下:架构

innodb_data_file_path=datafile1[,datafile2]...
复制代码

 用户能够经过多个文件组成一个表空间,同时制定文件的属性:性能

innodb_data_file_path = /db/ibdata1:1000M;/dr2/db/ibdata2:1000M:autoextend
复制代码

 这里讲/db/ibdata1和/dr2/db/ibdata2两个文件组成系统表空间。若是这两个文件位于不一样的磁盘上,磁盘的负载可能被平均,所以能够提升数据库的总体性能。两个文件的文件名以后都跟了属性,表示文件ibdata1的大小为1000MB,文件ibdata2的大小为1000MB,并且用完空间以后能够自动增加(autoextend)。学习

 设置innodb_data_file_path参数以后,因此基于InnoDB存储引擎的表的数据都会记录到该系统表空间中,若是设置了参数innodb_file_per_table,则用户能够将每一个基于InnoDB存储引擎的表产生一个独立的用户表空间。用户表空间的命名规则为:表名.ibd。  经过这种方式,用户不用将全部数据都存放于默认的系统表空间中,可是用户表空只存储该表的数据、索引和插入缓冲BITMAP等信息,其他信息仍是存放在默认的表空间中。spa

InnoDB表存储引擎文件

 上图显示InnoDB存储引擎对于文件的存储方式,其中frm文件是表结构定义文件,记录每一个表的表结构定义。操作系统

重作日志文件和归档文件

 默认状况下,在InnoDB存储引擎的数据目录下会有两个名为ib_logfile0和ib_logfile1的文件,这就是InnoDB的重作日志文件(redo log fiel),它记录了对于InnoDB存储引擎的事务日志。  当InnoDB的数据存储文件发生错误时,重作日志文件就能派上用场。InnoDB存储引擎可使用重作日志文件将数据恢复为正确状态,以此来保证数据的正确性和完整性。线程

 每一个InnoDB存储引擎至少有1个重作日志文件组(group),每一个文件组下至少有2个重作日志文件,如默认的ib_logfile0和ib_logfile1。  为了获得更高的可靠性,用户能够设置多个镜像日志组,将不一样的文件组放在不一样的磁盘上,以此来提升重作日志的高可用性。

 在日志组中每一个重作日志文件的大小一致,并以循环写入的方式运行。InnoDB存储引擎先写入重作日志文件1,当文件被写满时,会切换到重作日志文件2,再当重作日志文件2也被写满时,再切换到重作日志文件1。

 用户可使用innodb_log_file_size来设置重作日志文件的大小,这对InnoDB存储引擎的性能有着很是大的影响。

 若是重作日志文件设置的太大,数据丢失时,恢复时可能须要很长的时间;另外一方面,若是设置的过小,重作日志文件过小会致使依据checkpoint的检查须要频繁刷新脏页到磁盘中,致使性能的抖动。  重作日志相关和Checkpoint的机制能够阅读我以前文章的相应章节。MySQL探秘(三):InnoDB的内存结构和特性

重作日志的落盘机制

 InnoDB对于数据文件和日志文件的刷盘遵照WAL(Write ahead redo log) 和Force-log-at-commit两种规则,两者保证了事务的持久性。WAL要求数据的变动写入到磁盘前,首先必须将内存中的日志写入到磁盘;Force-log-at-commit要求当一个事务提交时,全部产生的日志都必须刷新到磁盘上,若是日志刷新成功后,缓冲池中的数据刷新到磁盘前数据库发生了宕机,那么重启时,数据库能够从日志中恢复数据。

写入机制

 如上图所示,InnoDB在缓冲池中变动数据时,会首先将相关变动写入重作日志缓冲中,而后再按时或者当事务提交时写入磁盘,这符合Force-log-at-commit原则;当重作日志写入磁盘后,缓冲池中的变动数据才会依据checkpoint机制择时写入到磁盘中,这符合WAL原则。  在checkpoint择时机制中,就有重作日志文件写满的判断,因此,如前文所述,若是重作日志文件过小,常常被写满,就会频繁致使checkpoint将更改的数据写入磁盘,致使性能抖动。

 操做系统的文件系统是带有缓存的,当InnoDB向磁盘写入数据时,有可能只是写入到了文件系统的缓存中,没有真正的“落袋为安”。  InnoDB的innodb_flush_log_at_trx_commit属性能够控制每次事务提交时InnoDB的行为。当属性值为0时,事务提交时,不会对重作日志进行写入操做,而是等待主线程按时写入;当属性值为1时,事务提交时,会将重作日志写入文件系统缓存,而且调用文件系统的fsync,将文件系统缓冲中的数据真正写入磁盘存储,确保不会出现数据丢失;当属性值为2时,事务提交时,也会将日志文件写入文件系统缓存,可是不会调用fsync,而是让文件系统本身去判断什么时候将缓存写入磁盘。日志的刷盘机制以下图所示。

log刷盘机制

 innodb_flush_log_at_commit是InnoDB性能调优的一个基础参数,涉及InnoDB的写入效率和数据安全。当参数值为0时,写入效率最高,可是数据安全最低;参数值为1时,写入效率最低,可是数据安全最高;参数值为2时,两者都是中等水平。通常建议将该属性值设置为1,以得到较高的数据安全性,并且也只有设置为1,才能保证事务的持久性。

后记

 咱们后续还会学习binlog文件以及数据文件的落盘机制,还有InnoDB事务相关的其余知识,请你们持续关注。

相关文章
相关标签/搜索