目录
2.redo log 也要写入磁盘,为什么不直接将缓冲数据写到磁盘?
1.如何维护持久性?
使用redolog,当数据发生修改时,先在 redo log 里面记录本次操作,然后再修改缓冲区中的数据。在事务提交时或者提交前,调用fsync接口对redo log进行刷盘。
如果MySQL数据库宕机了,重启的时候,只需要读取 redo log 里面的数据,就可以对数据库进行恢复。由于redo log是 WAL (Write Ahead Log)日志,也就是预写日志,在修改前,先写到日志里,所以保证了数据不会因为MySQL宕机而丢失数据,从而满足了持久性的要求。
2.redo log 也要写入磁盘,为什么不直接将缓冲数据写到磁盘?
因为redo log写入磁盘更容易,更快捷。
1.缓冲区修改的数据是随机的,所以刷脏是随机IO,redo log是追加操作,所以redo log落盘是顺序IO
2.刷脏是以数据页为单位,MySQL默认16KB,一页上面有个小修改,那整页都要写入,所以积累多一些数据,再一并刷脏,会大大提升性能。 而redo log 只记录的要修改的数据,无效IO少。
3.redo log什么时候落盘?
1.先说redo log位置
事务执行时,在进程内存的redolog buffer中
事务提交,执行 write 操作存到 page cache 里面
事务提交,执行 fsync 操作持久化到硬盘
2.事务提交前就可能会落盘
1.Innodb 有个后台线程,每1秒轮询一次,执行write 和 fsync 落盘
所以有可能事务提交前,它的redo log 就被后台线程持久化到硬盘了
2.参数 ,,,,,(挺长的不用背)设置为1,每次提交的时候,执行fsync ,落盘
(如果参数是0 ,表示每次提交事务的时候,redolog留在 redolog buffer里,如果参数是2,表示提交的时候,write 到page cache 里面。)
加入事务 A 执行到了一半,写了部分redo log 到redolog buffer里面,这时候有个事务B提交,如果参数设置为了1,那么会将 redo log buffer 里面的日志都刷到磁盘中,这时就会带上事务A 在redo log buffer 里面的日志一起持久化
3.redolog buffer 占用这个buffer 空间,默认是达到一半,会触发后台线程 落盘。
4.什么时候刷脏?
1.数据库空闲时、数据库正常关闭
2.redo log写满了,check point 需要向前推进,推进的区间涉及到的脏页需要刷到磁盘中
3.内存不够了
使用LRU算法,释放最少使用的页,如果是脏页,就执行checkpoint,刷到磁盘中去。
5.一条更新语句如何执行?redolog写入过程?
1.存储引擎:根据主键索引树,找到要更新的这行语句,如果在内存池中,就直接返回给执行器,否则,就读入到内存中,然后返回给执行器。
2.执行器:拿到记录,更新
3.存储引擎:将新纪录更新到内存池中,并设置redolog 状态为 prepare
4.执行器:生成 bin log,并写入磁盘
5.存储引擎:redo log 状态为 commit
6.事务提交完成。
如果在事务提交期间发生了崩溃:
1.若redo log 是commit状态,则直接提交
2.若redo log 是 prepare状态,判断 bin log,
若bin log 完整,就提交事务,否则回滚