https://dev.mysql.com/doc/refman/5.7/en/innodb-parameters.html#sysvar_innodb_flush_log_at_trx_commit
其中有一段是这么写的: With a value of 2, the contents of theInnoDB log buffer are written to the log file after each transaction commit and the log file is flushed to disk approximately once per second.
意思是:如果innodb_flush_log_at_trx_commit的值设为2,那么log buffer里的内容会在每次提交时被写入log file,然后logfile也会被flush到disk。
由于innodb的log file据我所知是在硬盘上的ib_logfile,所以对于这里的log file被flush到disk很疑惑,难道log buffer和disk之间还存在了一层可以缓存log file的结构?
在查阅了大量中英文资料后,总算有了初步的了解,暂总结于此。
一、名词解释
在innodb存储引擎中,有一种独有的log file,即redo log file,因此对于innodb存储引擎来说,就存在两种logfile:redo log和binlog.
redo log:即data目录下的ib_logfile0,ib_logfile1(个数由innodb_log_files_in_group控制),innodb存储引擎特有,在内存中有相应的redo log buffer。
因此写redo时的3层结构为:redo log buffer--->文件系统缓存中的redo logfile--->disk上的redo log file
binlog:默认在data目录下,也可以通过log_bin参数直接指定路径,文件名为默认为<hostname>-bin前缀的文件,在内存中没有log buffer。
因此写binlog时的2层结构为:文件系统缓存中的binlog--->disk上的binlog
二、二阶段日志写的流程
原图来自:https://jin-yang.github.io/post/mysql-group-commit.html
当开启binlog后,如果会话发出了commit的请求,那么在committed之前,一系列的流程为:
1.prepare阶段:
将log buffer的事务更改和事务commit信息写入文件系统缓存中的redo log file,注意log buffer和undo buffer(也叫undo page)是在事务执行过程中就即时生成的(undo默认在系统表空间中,5.6以后也可以自己指定独立的表空间),文件系统缓存中的redo log 是否flush到disk,取决于innodb_flush_log_at_trx_commit参数。
innodb_flush_log_at_trx_commit:
- 此值为0表示:redo log buffer的内容每秒会被写入文件系统缓存的redo log里,同时被flush(固化)到disk上的redo log file中。
- 此值为1表示:redo log buffer的内容会在事务commit时被写入文件系统缓存的redo log里,同时被flush(固化)到disk上的redo log file中。
- 此值为2表示:redo log buffer的内容会在事务commit时被写入文件系统缓存的redo log里,而文件系统缓存的redo log每秒一次被flush(固化)到disk上的redo log file中。
- sync_binlog=0:表示fsync()的调用完全交给操作系统,即文件系统缓存中的binlog是否刷新到disk完全由操作系统控制。
- sync_binlog=1:表示在事务提交时,binlog一定会被固化到disk
- sync_binlog=N(N>1):数据库崩溃时,可能会丢失N-1个事务,具体原理也详见https://jin-yang.github.io/post/mysql-group-commit.html
innodb二阶段日志提交机制
标签:不一致 server 两种 疑问 href write mit 资料 bubuko