引出
mysql作为关系性数据库的佼佼者, 离不开它优良的设计。 在mysql内部存在了很多种日志, 比如binlog, undo.log, relay.log 等等,今天主要介绍的是redo.log重做日志,这个日志非常重要,所以需要重点掌握它。 从名字上来看, redo.log 就跟数据恢复有关,没错它确实与mysql的数据有很大的关系。
为什么数据不直接写入磁盘了
磁盘的IO性能是我们必须要考虑的一个问题, 如果每次更新数据,都直接去操作磁盘,那么这样就会大大的降低数据库的性能, 体验肯定非常不好。于是乎,mysql的设计者,通过提出了先写日志,把要变化的数据先记录下来,然后在集中一起刷进磁盘里去。 这确实是个很好的办法。这里我们要知道一个前置知识,磁盘的顺序写和随机写等差别,经过数据论证,性能有比较大的差异。而数据刷盘就是随机写的情况,由于redo日志可以做到顺序写,所以先记录修改内容,这样性能将会有很大的提升。
mysql的数据存储,读取,更新
mysql的数据存储在磁盘中是以页为单位,默认是16KB的大小。 我们查询一条记录,从磁盘中不是仅仅就只查这一条记录,而是把该条记录所在的页全部加载出来,放在一个叫Buffer Pool中区域,可以理解为内存中的一块缓冲池中。 然后数据的更新也是直接在这块区域上更新。 同时更新的记录会先进入到redo.log buffer的区域,接着进行刷盘,写入到redo.log ,这个过程看上去还是比较绕,链路也比较长的,实际是非常快的。 这里写入redo.log是有特殊时机的, 有三种情况。 0: 每次事务提交,不进行刷盘, 由系统自行判断。 1:每次事务提交,进行刷盘, 默认就是这种情况。2: 每次事务提交只把redo.log buffer写入到page cache磁盘数据页的缓冲区中。 其中第一种,第三种都有可能存在数据丢失的情况。 写入到page cache中的数据, 后台线程会每隔1s钟,调用系统的fsyc方法进行刷盘,或者是redos log buffer达到buffer size一半的情况下,后台线程也会进行刷盘。
redo.log 日志
是InnoDB引擎中单独存在的,是一个日志组,所以可以是多个文件, 内部结构是环形数组,从头写到尾,回到头又重新开始。 其中包含write pos和checkpoint两个属性, 用于记录在日志写入的当前位置,一边写一边后移,以及擦除的位置, 也就是write pos要小于checkpoint, 其中要明确一点,事务开始, redo.log 就会开始写入, 这里与binlog日志之间存在二阶段提交的机制, binlog日志是事务提交完成后才开始写入,所以redo.log 存在prepare和commit两阶段,保证数据的完整性
小结
redo由于记录数据内容少,写入快,比直接将数据写入磁盘的过程,性能提升明显, 让数据库的并发能力大大的提高