1. Buffer Pool的简介
大家有没有想过?当我们将数据持久化到磁盘之后,下次进行crud的时候,持久化在磁盘中的数据是如何到达内存中供我们使用的?所以这里就要引入InnoDB存储引擎中一个重要的组件:缓冲池(Buffer Pool)。
update user set name = 'zhangsan' where id = 1 ;
当我们执行上面sql的时候,执行器会先到InnoDB存储引擎中的Buffer Pool 中查找“id = 1" 的数据是否存在?如果有的话就加上独占锁再处理。如果没有的话,就会就会将磁盘中的数据加载到缓冲池(Buffer Pool)中,接着对这行记录加上独占锁。
2. Undo Log(回滚日志)的简介
mysql中有个回滚的动作,大家有没有想过,这个回滚的动作是借助了InnoDB中的哪个组件实现的呢?所以这里就引入了InnoDB存储引擎中的一个重要组件-Undo Log日志。
undo log日志的执行原理:在更新数据之前,MySQL会提前生成undo log日志(日志中记录的是sql被修改之前数据,例如:假设原本 name = 'zhangsan' ,sql执行后name 被设置为:xxx,那么undo log中就记录了name = 'zhangsan' 和 'id'= 1 这些数据)。当事务提交的时候,并不会立即删除undo log,因为后面可能需要进行回滚(rollback)操作。undo log日志的删除是通过通过后台purge线程进行回收处理。
执行完上面的 sql语句后,Buffer pool中id= 1的那条记录就会变成name = 'xxx' ,此时候id= 1的这条数据属于脏数据,因为Buffer Pool中的数据name = 'xxx',但是磁盘中的name='zhangsan'。
3. Redo Log (重做日志)的简介
Redo Log称为重做日志,属于InnoDB存储引擎层的日志,记录物理页的修改信息,而不是某一行或几行修改成什么样。事物开始的时候就会写入Redo log Buffer 中,之后从Redo Log Buffer 刷到 os cache 中,最后调用文件系统的fsync函数将日志刷新到磁盘中,并且是顺序IO保证了性能,如果服务器突然停电,InnoDB引擎会使用Redo Log把数据库恢复到停电之前的数据。
Redo Log的刷盘策略:设置参数:innodb_flush_log_at_trx_commit
0:每秒一次,把log buffer写入os buffer,并调用fsync刷到磁盘
1:每次提交事务时,把log buffer写入os buffer,并调用fsync刷到磁盘
2:每次提交事务时,只是写入到os buffer,然后每秒一次调用fsync将日志刷新到磁盘
介绍Undo Log的时候,说此时id=1的数据为:脏数据,因为数据在Buffer Pool中还没有进行磁盘持久化,要是此时服务器宕机,那么我们修改数据的操作岂不是丢失了?所以,我们就要把对内存所做的修改写入到一个Redo Log Buffer 中,这也是内存中的一个缓冲区(redo log中记录的是你对这个数据做了什么修改,比如:id = 1这行记录修改了name='xxx'),所以此时还不安全,只有将Redo log Buffer 中的数据刷入到os cache 中,之后根据刷盘策略(innodb_flush_log_at_trx_commit)刷入到磁盘。此时要是mysql系统宕机了就不会丢失数据了,当再次重启时,会根据Redo Log的日志去恢复数据。
借道友法力一用:
========================== stay hungry stay foolish ==========================