表空间文件
InnoDB采用将存储的数据按表空间(tablesapce)进行存放的设计,在默认配置下会有一个初始大小为10MB,名为ibdata1的文件,该文件就是默认的表空间文件(tablespace file),用户可以通过参数innodb_data_file_path对其进行设置
如果设计了innodb_data_file_path参数,所有基于InnoDB存储引擎的表的数据都会记录到该共享表空间中,如果还设置了参数innodb_file_per_table,则用户可以将每一个基于InnoDB存储引擎的表产生一个独立表空间,独立表空间的命名为:表明.idb。
这些单独的表空间文件仅仅存储该表的数据、索引和插入缓冲BITMAP等信息,其余信息还是会放在默认的表空间中的。
重做日志文件
在默认情况下,InnoDB存储的数据目录会有两个名为ib_logfile0和ib_logfile1的文件,这两个就是重做日志文件(redo log file)
重做日志对InnoDB存储引擎至关重要,他们记录了对于InnoDB存储引擎的事务日志。
当实例或者介质失败时,InnoDB存储引擎会使用重做日志恢复到之前的状态,以此来保证数据的完整性
每个InnoDB存储引擎至少有1个重做日志文件组(group),每个文件组都至少有2个重做日志,比如默认的ib_logfile0和ib_logfile1,同一个日志组中的每个重做日志的大小都是一致的,并以循环写入的方式去运行,即会先去写重做日志1,重做日志1写满后会切换至重做日志2(此时会对重做日志1进行回收空间利用,回顾之前的Master Thread执行),但重做日志2也写满后,再用重做日志1。
关于重做日志镜像组
首先先认识什么是高可用性:高可用性就是指尽可能的减少停止服务的时间(由于某种原因,比如磁盘损坏,文件缺失)
重做日志镜像组可以提升高可用性,将镜像组放在别的磁盘上,那么一旦重做日志出现了问题,可以用镜像组来进行替代。
重做日志受下列的参数影响
- innodb_log_file_size
- innodb_log_files_in_group
- innodb_mirrored_log_groups
- innodb_log_group_home_dir
innodb_log_file_size决定了每一个重做日志文件的大小、
innodb_log_files_in_group指定了每个日志文件组这种重做日志文件的数量(默认为2)
innodb_mirrored_log_groups指定了日志文件镜像组的数量(默认为1,表示只有一个日志文件组,没有镜像)
innodb_log_group_home_dir指定了日志文件组所在的路径(默认为./,为根目录)
重做日志的大小设置
重做日志的大小设置对于InnoDB存储引擎的性能有着非常大的影响,如果太大,会导致恢复时载入重做日志会需要很长的时间,如果太小,一个事务的日志可能需要来回切换好几次重做日志(重做日志写入的循环性),此外重做日志太小会导致频繁地发生async checkpoint(前面体系架构中提到过的,重做日志不可用时,发生的checkpoint),导致性能的抖动。
重做日志里面有一个capacity变量,该值代表了最后的检查点不能超过这个阈值,如果超过则必须将缓冲池中的一些脏页刷新进磁盘中(刷新进去就持久化了,重做日志就不需要这部分内容,可以释放这部分内容来重用空间),即发生async checkpoint,进行刷新脏页,这时候会导致用户阻塞的。
重做日志与二进制日志的区别
二进制日志记录所有与MySQL数据库相关的事务日志记录(包括其他引擎),但重做日志只记录InnoDB或者本身引擎,而且是关于事务方面的事务日志。
其次是记录内容的不同,二进制日志是记录事务具体操作内容,而InnoDB的重做日志记录的是每个页的更改的物理情况
此外是写入的时间也不同,二进制日志是仅在事务提交前进行提交,即无论该事务多大,它只会提交一次,而在事务进行过程中,由于事务持久性的影响,在一个事务中,重做日志必须不断的进行更新写入。
重做日志的条目结构
重做日志的条目结构,即重做日志里面的内容,总共有以下4个部分
- redo_log_type:占用1字节,表示重做日志的类型
- space:占用小于4字节,表示表空间的ID,但是采用压缩方式表示
- page_no:表示页的偏移量,同样采用压缩的方式
- redo_log_body:表示重做日志的数据部分,恢复时,要调用对应函数才可以解析
前面已经提到过,重做日志的写入也不是直接写,而是先写入一个重做日志缓冲中,然后按照一定的条件顺序地被刷新进日志文件
重做日志写入的大小
从重做日志缓冲往磁盘写入时,是按照512个字节进行写入的,也就是一个扇区的大小进行写入
因为扇区是写入的最小单位,因此可以保证写入必定是成功的,因此在重做日志的写入过程中不需要有两次写的特性(double write,前面提到过的InnoDB特性)
重做日志刷新的条件
Master Thread会定时进行重做日志刷新,不论事务是否提交,除此之外,还有另一个触发写磁盘的过程是由名为innodb_flush_log_at_trx_commit控制,表示在提交操作时,处理重做日志的方式
SHOW VARIABLES LIKE "innodb_flush_log_at_trx_commit";
- 0:代表当提交事务时,并不会将重做日志写入磁盘上的重做日志文件,而是等待主线程的刷新
- 1:代表当提交事务时,将重做日志缓冲同步到磁盘中,即伴有fsync的调用(同步,写入然后保存)
- 2:代表当提交事务时,将重做日志缓冲同步到磁盘中,只不过是异步写入,即写入文件系统的缓存中(交由文件系统进行写入),因此不可以完全保证commit时肯定会写入重做日志文件
为了保证事务的ACID中的持久性,必须将innodb_flush_log_at_trx_commit设置为1,就是当事务提交时,就必须确保事务都已经写入重做日志,那么此时数据库发生宕机时,就可以通过重做日志文件恢复,并保证可以恢复已经提交的事务,如果设置为0或2,很有可能会导致部分事务的丢失,0的话,很可能会导致丢失,但如果是2的话,如果只是MySQL停止服务,但服务器没有宕机关机,还是可以通过文件系统的缓存来恢复重做日志。