执行select * from account时mysql底层大致的流程图如下所示。
innodb_flush_log_at_trx_commit
:这个参数控制 redo log 的写入策略,它有三种可能取值:
设置为0:修改完buffer pool内的数据后。只把数据写入redo buffer log内存中,不写入redo log文件中。这样如果数据库宕机redo日志文件可能会丢失一部分数据。
设置为1(默认):修改完buffer pool内的数据后,先写入redo buffer log内存中,然后再写入到操作系统的page cache中,再持久化到redo日志文件中。(最安全)
设置为2:修改完buffer pool内的数据后,先写入到redo buffer log内存中,然后只写入到page cache操作系统的内存中。这会导致如果操作系统宕机了,page cache内存中的数据还没有写入到磁盘导致数据丢失。
![](https://img-blog.csdnimg.cn/direct/c32d86c26ab44692b06001ea4cd445c6.png)
binlog写入磁盘的机制
sync_binlog=0时(默认)
每次只写入到操作系统的page cache中去,然后有操作系统自行去执行fsync函数刷入到binlog日志文件中。这样性能能得到很好的提升,但是如果操作系统还没有把数据刷入到binlog日志文件中就发生了宕机时会导致数据丢失。但是mysql宕机不会有影响 。
sync_binlog=1时
每次写入到操作系统的page cache中后会马上执行fsnyc函数立刻刷入到binlog日志文件中去,保证数据不会丢失。这种方式是最安全的。
sync_binlog=N时
写入到操作系统的page cache中的数据达到N次之后再调用fsync函数批量刷入到binlog日志文件中去。这种方式如果在page cache中的数据还没有写入磁盘操作系统宕机了,会导致数据丢失N个。但是mysql宕机不会有影响 。
为什么会有redo log和binlog两份日志呢?
因为最开始 MySQL 里并没有 InnoDB 引擎,mysql自带的引擎是MyISAM,而InnoDb是另外的一个公司以插件的方式引入到mysql的。
其中最重要的一点是MYISAM引擎是不支持事务的,那么也就没有发生意外崩溃或故障时,能够保证数据的一致性和持久性的能力的。因此innodb使用了另外的一套日志系统来实现这个功能也就是redo日志,即就算是数据库出现崩溃宕机,通过redo日志重启数据库也能保证数据不会丢失。重新把redo日志内的数据与磁盘数据做比较,发现不同就把redo 日志的内容刷入到磁盘idb文件中保证数据的一致性。