数据库——redo日志和undo日志

redo日志

InnoDB存储引擎是以页为单位来管理存储空间,我们进行的增删改查实质都是在访问页面。在真正访问页面之前,需要把磁盘上的页缓存到内存中的Buffer Pool之后才可以访问。

在前面提到事务的四个特性时,持久性指示对于一个已经提交的事务,在事务提交后即使系统发生崩溃,这个事务对数据库所作的修改也不能丢失。如果我们只在Buffer Pool中修改了页面,假设事务提交后突然出现故障,导致内存中的数据失效,那么已提交的事务的修改也随之丢失了。那么我们又该如何保证这个持久性呢:在事务调教完成前,把事务修改的所有页面都刷新到磁盘。但这个做法有问题:

  • InnoDB是以页为单位进行磁盘IO的,有时如果我们仅修改了页面的一个字节,就把一个完整的页面从内存刷新到磁盘,这未免也态浪费了。
  • 一个事务可能包含很多语句,即使是一条语句也可能修改许多页面,这些页面可能并不相邻,需要进行很多随机IO。

因此我们可以记录修改的哪些东西,这样即使系统崩溃了,重启后按照记录的步骤更新数据页即可。记录这些修改步骤的内容称为redo日志。

 

Mini-Transaction

以组的形式写入redo日志

执行语句的过程中产生的redo日志被划分为若干个不可分割的组,比如:

  • 更新name属性产生的redo日志是不可分割的;
  • 向聚簇索引对应B+树的页面中插入一条记录产生的redo日志是不可分割的。

以向某个索引对应B+树的页面中插入一条记录为例,在定位到这条记录需要插入到的数据页之后,可能有两种情况:

(1)该数据页的剩余空间足够容纳一条待插入记录,这种情况称为乐观插入。

(2)该数据页的剩余空间不足,则需要进行页分裂:新建一个叶子节点,把原数据页种的一部分复制到这个新数据页中,再把待插入记录添加进去,最后还要在内节点中添加一条目录项记录来指向这个新创建的页。这种情况称为悲观插入。这个步骤需要对多个页面进行修改,意味着会产生多条redo日志。

插入一条记录的过程必须是原子的,也就是说上面的所有步骤要么全部完成,要么没有执行。因此在执行这些需要原子性操作时,必须要以的形式来记录redo日志。某个组中的redo日志,要么全部恢复,要么一条也不恢复。

Mini-Transaction的概念

Mini-Transaction是指对底层页面中的一次原子访问过程,简称mtr。比如向某个索引对应的B+树种插入一条记录算是一个mtr,

事务中的每一条语句是由若干个mtr组成,而一个mtr可以包含若干条redo日志。

 

redo日志 的组成

Redo日志分为:

  • redo日志缓存redo log buffer,它保存在内存中,是易失的。
  • redo日志文件redo log file,它保存在磁盘中,是持久的。

redo日志缓存

通过mtr生成的redo日志放在一个页中,该页称为block。由于磁盘速度过慢,在写入redo日志时,不能直接写到磁盘。因此服务器在启动时就向OS申请了一片 被称为redo日志缓存的连续内存空间。每生成一条redo日志,就将其暂存到一个地方。等mtr结束后,将该过程产生的一组redo日志全部赋值到redo日志缓存中。

你可能感兴趣的:(数据库基础)