1.缓冲池

查询时如果缓冲池中有数据,就不用去查磁盘了。
更新数据时,比如对“id=10”这一行数据,会先查看缓冲池是否有此行数据,如果没有,那么会从磁盘里加载到缓冲池里来,并对这行数据加锁。
2.undo日志文件
假设“id=10”这行数据的name原来是“LOL”,现在要更新为“CSGO”,先要将“name=LOL”和“id=10”这些信息,写到undo日志文件中,我们就可以根据undo日志文件对事物进行回滚。
3.更新buffer pool中的缓存数据
当把旧值写入undo日志文件之后,会先更新buffer pool中的数据。
此时缓存中的数据是脏数据,因为磁盘中此时还是旧值。
4.Redo Log Buffer

redo日志存放修改后的信息,比如修改后“id=10”,“name=CSGO”。
如果redo日志还未写入数据库,数据库就宕机,那么磁盘上的数据还是停留在更新之前的样子。
5.事务提交刷新Redo日志的策略

提交事务后,会根据一定策略把redo日志从redo log buffer里刷到磁盘文件里去。这个策略是通过innodb_flush_log_at_trx_commit 来配置的。
当这个参数的值为0的时候,提交事务时,不会把redo log buffer里的数据刷入磁盘文件,此时有可能会出现提交事务了,结果mysql宕机了,此时内存中的数据全部丢失的情况。
当这个参数的值为1的时候,提交事务时,会把redo log buffer里的数据刷入磁盘文件,只要事务提交成功,那么redo log就必然在磁盘里。
当这个参数的值为2的时候,提交事务时,会把redo日志写入磁盘文件对应的os cache中去,而不是直接进入磁盘文件,可能1秒后才会把os cache里的数据写入到磁盘文件里。
一般建议redo日志刷盘策略设置为1,保证事务提交之后,数据绝对不能丢失。
6.binlog
redo log又称重做日志文件,用于记录事务操作的变化,记录的是数据修改之后的值,不管事务是否提交都会记录下来。
binlog叫做归档日志,他里面记录的是偏向于逻辑性的日志,类似于“对users表中的id=10的一行数据做了更新操作,更新以后的值是什么” 。
提交事物的时候,会把redo log日志写入磁盘文件中,同时还会把这次更新对应的binlog日志写入磁盘文件中。
binlog日志的刷盘策略:
sync_binlog参数可以控制binlog的刷盘策略,默认值是0,此时把binlog写入磁盘的时候,不是直接进入磁盘,而是进入os cache中。如果此时mysql宕机,那么内存中的数据就会丢失。
如果sync_binlog参数设置为1的话,那么在提交事务时,会强制把binlog写入到磁盘中。
7.基于binlog和redo log完成事务的提交
当binlog写入磁盘后,会完成最终的事务提交。此时会把本次更新对应的binlog文件名称和这次更新的binlog日志在文件中的位置,都写入到redo log日志文件里去,同时在redo log日志文件里写入一个commit标记。
在完成这件事之后,才算最终完成了事物的提交。
redo日志写入commit标记的意义:
假设我们在提交事务的时候,一共有上图中的5、6、7三个步骤,必须是三个步骤都执行完毕,才算是提交了事务。那么在我们刚完成步骤5的时候,也就是redo log刚刷入磁盘文件的时候,mysql宕机了 ,这个时候因为没有最终的事务commit标记在redo日志里,所以此次事务可以判定为不成功。不会说redo日志文件里有这次更新的日志,但是binlog日志文件里没有这次更新的日志,不会出现数据不一致的问题。
如果要是完成步骤6的时候,也就是binlog写入磁盘了,此时mysql宕机了 ,因为没有redo log中的最终commit标记,因此此时事务提交也是失败的。
必须是在redo log中写入最终的事务commit标记了,然后此时事务提交成功,而且redo log里有本次更新对应的日志,binlog里也有本次更新对应的日志 ,redo log和binlog完全是一致的。
8.后台IO线程随机将内存中更新后的脏数据刷回磁盘
在第3步中缓存中的数据是脏数据,因为磁盘中此时还是旧值。所以mysql中有一个后台的IO线程,会在之后的某个时间里,随机的把内存buffer pool中的脏数据刷回到磁盘中。
9.InnoDB存储引擎架构原理总结
InnoDB存储引擎主要就是包含了buffer pool、redo log buffer等内存里的缓存数据,同时还包含了undo日志文件、rodo日志文件,同时mysql还有自己的binlog文件。
在执行更新语句时,每条SQL语句,都会对应修改buffer pool里的缓存数据、写undo日志、写redo log buffer几个步骤;当事务提交时,一定会把redo log刷入磁盘,binlog刷入磁盘,完成redo log中的事务commit标记;最后,IO线程会将buffer pool里的脏数据刷入磁盘中。
10.问题:执行更新操作的时候,为什么不直接修改磁盘上的数据?
为了减少与磁盘的IO交互,在对数据库增改删操作时,实际主要都是针对内存里的Buffer Pool中的数据进行的。
