MySQL(InnoDB剖析):13---文件之(InnoDB存储引擎文件(表空间文件(.ibd)、重做日志文件(redo log)))

  • 前面介绍的文件都是MySQL数据库本身的文件,和存储引擎无关。本文介绍与存储引擎有关的独有的文件。本文将介绍与InnoDB密切相关的文件,这些文件包括重做日志文件、表空间文件

一、表空间文件

  • 功能:InnoDB采用将存储的数据按表空间(tablespace)进行存放的设计
  • 默认配置下会有一个初始大小为10MB,名为idbata1的文件(见下图),该文件就是默认的表空间文件

innodb_data_file_path参数

  • 该参数用于指定InnoDB使用的表空间文件。设置了这个参数后,所有基于InnoDB存储引擎的表的数据都会被记录到该共享表空间中
  • 例如下面显示InnoDB默认使用的表空间文件
show variables like 'innodb_data_file_path'\G;

  • 该参数的设置格式如下:

  • 如果用户想通过多个文件组成一个表空间,并且制定文件的属性,则可以使用如下的案例格式:
    • 这里把/db/ibdata1和/dr2/db/ibdata2两个文件用来组成表空间。若这两个文件位于不同的磁盘上,磁盘的负载可能被平均,因此可以提高数据库的整体性能
    • 同时文件名后面还跟了文件大小属性:表示ibdata1的大小为2000MB,ibdata2的大小为2000MB,如果用完了这2000MB,该文件会自动增长

innodb_file_per_table参数

  • 如果设置了这个参数,则用户可以将每个基于InnoDB存储引擎的表产生一个独立表空间。通过这样的方式,用户不用将所有数据都存放于默认的表空间中。该参数默认关闭,不使用独立表空间文件
show variables like 'innodb_file_per_table'\G;

  • 独立表空间的命名规则为:表名.ibd
  • 需要注意的是,这些独立的表空间文件仅存储该表的数据、索引、插入缓冲BITMAP等信息,其余信息还是存放在默认的表空间中。下图显示了InnoDB存储引擎对于文件的存储方式:

  • 下面这台MySQL数据库服务器设置了该参数,可以观察到:
    • 表Profile、t1、t2都是基于InnoDB存储的表
    • 由于设置了参数innodb_file_per_table=ON,因此产生了独立的.ibd独立表空间文件

二、重做日志文件(redo log)

  • 重做日志文件简介:
    • 在默认情况下,在InnoDB存储引擎的数据目录下会有两个名为ib_logfile0和ib_logfile1的文件。在MySQL官方手册中称其为InnoDB存储引擎的日志文件,不过更准确的定义应该是重做日志文件(redo log file)
    • 为什么强调是重做日志文件呢?因为重做日志文件对于InnoDB存储引擎至关重要,它们记录了对于InnoDB存储引擎的事务日志
    • 当实例或介质失败时,重做日志文件就能派上用场。例如,数据库由于所在主机掉电导致实例失败,InnoDB存储引擎会使用重做日志文件恢复到掉电前的时刻,以此来保证数据的完整性

重做日志文件组的概念

  • 每个InnoDB存储引擎至少有1个重做日志文件组每个文件组下至少有2个重做日志文件(如默认的ib_logfile0和ib_logfile2)
  • 为了得到更高的可靠性,用户可以设置多个的镜像日志组,将不同的文件组放在不同的磁盘上,以此来提高重做日志高可用性
  • 在日志组中每个重做日志文件的大小一致,并以循环写入的方式运行。例如:InnoDB有3个重做日志文件。InnoDB先写重做日志文件0,当文件0写满后,接着写重做日志文件1,当文件1写满后,开始重写日志文件2,当重写日志文件2写满后,又开始写重做日志文件0。下图显示了一个拥有3个重做日志文件的重做日志文件组

innodb_log_file_size参数

  • 该参数指定每个重做日志文件的大小
  • 在InnoDB 1.2.x之前,重做日志文件总的大小不得大于等于4GB,而1.2.x版本将该限制扩大为了512GB
show variables like 'innodb_log_file_size'\G;

innodb_log_files_in_group参数

  • 该参数指定了日志文件组中重做日志文件的数量。默认为2
show variables like 'innodb_log_files_in_group'\G;

 

innodb_mirrored_log_groups参数

  • 该参数指定了日志镜像文件组的数量
  • 默认为1,表示只有一个日志文件组,没有镜像。若磁盘本身已经做了高可用的方案,如磁盘列阵,那么可以不开启重做日志镜像的功能
show variables like 'innodb_mirrored_log_groups'\G;

innodb_log_group_home_dir参数

  • 该参数指定了日志文件组所在路径
  • 默认为“./”,表示在MySQL数据库的数据目录下
show variables like 'innodb_log_group_home_dir'\G;

重做日志文件的大小问题

  • 上面介绍了innodb_log_file_size参数用来决定每个重做日志文件的大小。重做日志文件的大小设置对于InnoDB存储引擎的性能有着非常大的影响:
    • 一方面,重做日志文件不能设置的太大,如果设置得很大,在恢复时可能需要很长的时间
    • 另一方面,重做日志文件又不能设置的太小,否则可能导致一个事务的日志需要多次切换重做日志文件
    • 此外,重做日志文件太小会导致频繁地发生async checkpoint(见文章:https://blog.csdn.net/qq_41453285/article/details/104091059),导致性能的抖动
  • 例如,用户可能在错误日志中看到如下警告信息:
    • 下面的错误集中在前两行。这是因为重做日志有一个capacity变量,该值代表了最后的检查点不能超过这个阈值,如果超过则必须将缓冲池中脏页列表中的部分脏数据写回磁盘,这时会导致用户线程的阻塞

重做日志文件与二进制日志文件的区别

  • 重做日志文件与二进制日志都是记录事务的日志,两者的区别如下:
    • 首先,二进制日志会记录所有与MySQL数据库有关的日志记录,包括InnoDB、MyISAM、Heap等其他存储引擎的日志。而InnoDB存储引擎的重做日志只记录与该存储引擎本身的事务日志
    • 其次,记录的内容不同,无论用户将二进制日志文件记录的格式设为STATEMENT、ROW还是MIXED,其记录的都是关于一个事务的具体操作内容,即该日志是逻辑日志。而InnoDB存储引擎的重做日志文件记录的是关于每个页(Page)的更改的物理情况
    • 此外,写入的时间也不同,二进制日志文件仅在事务提交前进行提交,即只写磁盘一次,不论这是该事务多大。而在事务进行的过程中,却不断有重做日志条目被写入到重做日志文件中

重做日志条目结构

  • 在InnoDB中,对于各种不同的操作有着不同的重做日志格式
  • 到InnoDB 1.2.x版本为止,总共定义了51种重做日志类型。虽然各种重做日志的类型不同,但是它们有着基本的格式。下表显示了重做日志条目的结构:
    • redo_log_type:占用1字节,表示重做日志的类型
    • space:表示表空间的ID,但采用压缩的方式,因此占用的空间可能小于4字节
    • page_no:表示页的偏移量,同样采用压缩的方式
    • redo_log_body:表示每个重做日志的数据部分,恢复时需要调用相应的函数进行解析

重做日志的写入过程

  • 在前面几篇文章中我们已经提到,写入重做日志文件的操作不是直接写,而是先写入一个重做日志缓冲(redo log buffer)中,然后按照一定的条件顺序地写入日志文件
  • 下图很好地诠释了重做日志的写入过程:

  • 从重做日志缓冲往磁盘写入时,是按512个字节,也就是一个扇区的大小进行写入。因为扇区是写入的最小单位,因此可以保证写入必定是成功的,因此在重做日志的写入过程中不需要有doublewrite

innodb_flush_log_at_trx_commit参数

  • 前面提到过从日志缓冲中写入磁盘上的重做日志文件是按一定条件进行的,这些条件如下:
    • 一个是前面在介绍“Master Thread”的文章中提到的,在主线程中每秒会将重做日志缓冲写入磁盘的重做日志文件中,不论事务是否已经提交
    • 另一个触发写磁盘的过程是由innodb_flush_log_trx_commit参数控制的,表示在提交(commit)操作时,处理重做日志的方式
  • 该参数的取值如下:
    • 0:当提交事务时,并不将事务的重做日志写入磁盘上的日志文件,而是等待主线程每秒的刷新
    • 1(默认值):在执行commit时将重做日志缓冲同步写到磁盘,即即伴有fsync的调用
    • 2:表示将重做日志异步写到磁盘,即写到文件系统的缓存中
show variables like 'innodb_flush_log_at_trx_commit'\G;

 

  • 因此不能完全保证在执行commit时肯定会写入重做日志文件,只是有这个动作(commit)发生
  • 因此为了保证实物的ACID中的持久性,必须将innodb_flush_log_trx_commit设置为1,也就是每当有事务提交时,就必须确保事务都已经写入重做日志文件。那么当数据库因为意外发生宕机时,可以通过重做日志文件恢复,并保证可以恢复已经提交的事务。而将重做日志文件设置为0或2,都有可能发生恢复时部分事务的丢失不同之处在于设置为2时,当MySQL数据库发生宕机而操作系统及服务器并没有发生宕机时,由于此时未写入磁盘的事务日志保存在文件系统缓存中,当恢复时同样能保证数据不丢失
发布了1378 篇原创文章 · 获赞 924 · 访问量 28万+

猜你喜欢

转载自blog.csdn.net/qq_41453285/article/details/104115914
今日推荐