在默认情况下,在innodb存储引擎的数据目录下会有两个名为ib_logfile0和ib_logfile1的文件。在MYSQL官方手册中将其称为innodb存储引擎的日志文件,不过准确的定义应该是重做日志文件(redo log file).
当实例或介质失败时,重做日志文件就能派上用场。例如,数据库由于所在主机掉电导致实例失败,innodb存储引擎会使用重做日志回复到掉电前的时刻,以此来保证数据的完整性。
每个innodb存储引擎至少有一个重做日志文件组(group),每个文件组下至少有两个重做日志文件,如默认的ib_logfile0和ib_logfile1.为了得到更高的可靠性,用户可以设置多个的镜像日志组(mirrored log groups)将不同的文件组放在不同的磁盘上,以此提高重做日志的高可用性。在日志组中每个重做日志文件的大小一致,并以循环写入的方式运行。innodb存储引擎先写重做日志文件1,当达到文件的最后时,会切换至重做日志文件2,再当冲走日志文件2也被写满时,会再切换到重做日志文件1中。如图:
下列参数影响着重做日志文件的属性:
innodb_log_file_size ---每个重做日志文件的大小
innodb_log_files_in_group --日志组中重做日志文件的数量
innodb_mirrored_log_groups ----5.7版本取消了此参数
innodb_log_group_home_dir ----日志组目录
重做日志文件大小很重要,太大恢复时间过长,太小可能导致一个事务的日志需要多次切换重做日志文件,也会导致频繁的发生async checkpoint
重做日志写入过程
从重做日志缓冲往磁盘写入时,是按512个字节,也就是一个扇区的大小进行写入。因为扇区是写入的最小单位,因此可以保证写入必定是成功的。因此在重做日志的写入过程中不需要有doublewrite.
主线程每秒会将重做日志缓冲写入磁盘的重做日志文件中,不论事务是否已经提交。另一个触发写磁盘的过程是由参数innodb_flush_log_at_trx_commit控制,表示在提交(commit)操作时,处理重做日志的方式。
参数innodb_flush_log_at_trx_commit的有效值有0、1、2。0代表当提交事务时,并不将事务的重做日志写入磁盘的日志文件,而是等待主线程每秒的刷新。1和2不同的地方在于:1表示在执行commit 时将重做日志缓冲同步写到磁盘,即伴有fsync的调用。2表示将重做日志异步写到磁盘,即写到文件系统的缓存中。因此不能完全保证在执行commit时肯定会写入重做日志文件,只是有这个动作发生。
因此 为了保证事务的ACID特性,就必须把innodb_flush_log_at_trx_commit设置为1,也就是每当有事务提交时,就必须确保事务都已经吸入重做日志文件。那么当数据库因为意外发生宕机时,可以通过重做日志文件恢复,并保证可以恢复已经提交的事务。而将重做日志文件设置为0或2,都有可能发生恢复时部分事务的丢失。不同之处在于,设置为2时,当MYSQL数据库发生宕机而操作系统及服务器并没有发生宕机时,由于此时未吸入磁盘的事务日志保存在文件系统缓存中,当恢复时同样能保证数据不丢失。