《MySQL系列-InnoDB引擎23》文件-InnoDB存储引擎文件-重做日志文件

Posted DATA数据猿

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了《MySQL系列-InnoDB引擎23》文件-InnoDB存储引擎文件-重做日志文件相关的知识,希望对你有一定的参考价值。

InnoDB存储引擎文件

  之前介绍的文件都是mysql数据库本身的文件,和存储引擎无关。除了这些文件外,每个表存储引擎都有其自己独有的文件。本节将具体介绍与InnoDB存储引擎密切相关的文件,这些文件包括重做日志文件、表空间文件。

重做日志文件

  在默认情况下,在InnoDB存储引擎的数据目录下会有两个名为ib_logfile0ib_logfile1的文件。在MySQL中称其为InnoDB存储引擎的日志文件,也可以称其为重做日志文件(redo log file)。为什么强调是重做日志文件呢?因为重做日志文件对于InnoDB存储引擎至关重要,记录着InnoDB存储引擎的事务日志。

  当实例或介质失败(media failure)时,重做日志文件就能派上用场。例如,数据库由于所在主机掉电导致实例失败,InnoDB存储引擎会使用重做日志恢复到掉电前的时刻,以此来保证数据的完整性。

  每个InnoDB存储引擎至少有1个重做日志文件组,每个文件组下至少有2个重做日志文件,如默认的ib_logfile0ib_logfile1。为了得到更高的可靠性,用户可以设置多个镜像日志组,将不同文件组放在不同的磁盘上,以此提高重做日志的高可用性。

下列参数影响着重做日志的属性:

  • innodb_log_file_size

    该参数指定每个重做日志文件的大小

    mysql> show variables like 'innodb_log_file_size';
    +----------------------+----------+
    | Variable_name        | Value    |
    +----------------------+----------+
    | innodb_log_file_size | 50331648 |
    +----------------------+----------+
    1 row in set (0.00 sec)
    
  • innodb_log_files_in_group

    该参数指定了日志文件组中重做日志文件的数量,默认为2

    mysql> show variables like 'innodb_log_files_in_group';
    +---------------------------+-------+
    | Variable_name             | Value |
    +---------------------------+-------+
    | innodb_log_files_in_group | 2     |
    +---------------------------+-------+
    1 row in set (0.00 sec)
    
  • innodb_mirrored_log_groups

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

  • innodb_log_group_home_dir

    该参数指定了日志文件组的路径,默认为./,表示MySQL数据库的数据目录下。

  重做日志的大小设置对于InnoDB存储引擎的性能有非常大的影响。一方面重做日志文件不能设置太大,如果设置很大,在恢复时可能需要很长的时间;另一方面又不能设置的太小,否则可能导致一个事务的日志需要多层切换重做日志文件。此外,重做日志文件太小会导致频繁发生async checkpoint,导致性能的抖动。例如会看到如下的警告信息:

160719 13:43:04  InnoDB: ERROR: the age of the last checkpoint is 9448350,
InnoDB: which exceeds the log group capacity 9433498.

  当出现以上问题的时候,可以关闭数据库服务,然后将两个重做日志文件备份并删除,然后修改my.cnf文件,给参数innodb_log_file_size分配更大的空间,最后启动数据库服务。

  而为什么出现这种问题呢?主要是因为重做日志有一个capacity变量,该值代表了最后的检查点不能超过这个阈值,如果超过则必须将缓冲池(innodb buffer pool)中脏页列表(flush list)中部分脏数据写回磁盘,这时会导致用户线程的阻塞。

二进制日志和重做日志有什么区别呢?

  首先,二进制日志会记录所有与MySQL数据库有关的日志记录,包括InnoDB、MyISAM、Heap等其他存储引擎的日志。而InnoDB的重做日志只记录有关本身的事务日志。

  其次,记录的内容不同,二进制日志的各种类型日志,记录的都是关于事务的具体操作内容,即该日志是逻辑日志。而InnoDB存储引擎的重做日志文件记录的是关于每个页(Page)的更改的物理情况。

  最后,两者写入的时间也不同,二进制日志仅在事务提交前进行提交,即只写磁盘一次,不论该事务多大。而在事务进行的过程中,却不断有重做日志条目(redo entry)被写入到重做日志文件中。

重做日志写流程?

  写入重做日志的操作不是直接写,而是先写入一个重做日志缓冲(redo log buffer)中,然后按照一定的条件顺序的写入日志。

  从重做日志缓冲往磁盘写入时,是按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数据库发生宕机而操作系统及服务器并没有发生宕机时,由于此时未写入磁盘的事务日志保存在文件系统缓存中,当恢复时同样能保证数据不丢失。

mysql> show variables like 'innodb_flush_log_at_trx_commit';
+--------------------------------+-------+
| Variable_name                  | Value |
+--------------------------------+-------+
| innodb_flush_log_at_trx_commit | 1     |
+--------------------------------+-------+
1 row in set (0.00 sec)

以上是关于《MySQL系列-InnoDB引擎23》文件-InnoDB存储引擎文件-重做日志文件的主要内容,如果未能解决你的问题,请参考以下文章

《MySQL系列-InnoDB引擎27》表-文件格式

《MySQL系列-InnoDB引擎13》文件-参数文件

《MySQL系列-InnoDB引擎13》文件-参数文件

《MySQL系列-InnoDB引擎21》文件-PID文件

《MySQL系列-InnoDB引擎20》文件-套接字文件

《MySQL系列-InnoDB引擎14》文件-日志文件-错误日志