图文结合带你搞定MySQL日志之Undo log(回滚日志)


  • GreatSQL社区原创内容未经授权不得随意使用,转载请联系小编并注明来源。
  • GreatSQL是MySQL的国产分支版本,使用上与MySQL一致。


文章导读:

什么是Undo Log?

Undo:意为撤销或取消,以撤销操作为目的,返回某个状态的操作。

Undo Log:数据库事务开始之前,会将要修改的记录放到Undo日志里,当事务回滚时或者数据库崩溃时,可以利用UndoLog撤销未提交事务对数据库产生的影响。

Undo Log是事务原子性的保证。在事务中更新数据的前置操作其实是要先写入一个Undo Log

如何理解Undo Log

事务需要保证原子性,也就是事务中的操作要么全部完成,要么什么也不做。但有时候事务执行到一半会出现一些情况,比如:

  • 情况一:事务执行过程中可能遇到各种错误,比如服务器本身的错误,操作系统错误,甚至是突然断电导致的错误。
  • 情况二:DBA可以在事务执行过程中手动输入ROLLBACK语句结束当前事务的执行。 以上情况出现,我们需要把数据改回原先的样子,这个过程称之为回滚。

每当我们要对一条记录做改动时(这里的改动可以指INSERT、DELETE、UPDATE),都需要"留一手"——把回滚时所需的东西记下来。比如:

  • 你插入一条记录时,至少要把这条记录的主键值记下来,之后回滚的时候只需要把这个主键值对应的记录删掉就好了。(对于每个INSERT, InnoDB存储引擎会完成一个DELETE)
  • 你删除了一条记录,至少要把这条记录中的内容都记下来,这样之后回滚时再把由这些内容组成的记录插入到表中就好了。(对于每个DELETE,InnoDB存储引擎会执行一个INSERT)
  • 你修改了一条记录,至少要把修改这条记录前的旧值都记录下来,这样之后回滚时再把这条记录更新为旧值就好了。(对于每个UPDATE,InnoDB存储引擎会执行一个相反的UPDATE,将修改前的行放回去)

MySQL把这些为了回滚而记录的这些内容称之为撤销日志或者回滚日志(即Undo Log)。注意,由于查询操作(SELECT)并不会修改任何用户记录,所以在杳询操作行时,并不需要记录相应的Undo日志

此外,Undo Log会产生Redo Log,也就是Undo Log的产生会伴随着Redo Log的产生,这是因为Undo Log也需要持久性的保护。

Undo Log的功能

  • 提供数据回滚-原子性

    当事务回滚时或者数据库崩溃时,可以利用Undo Log来进行数据回滚。
  • 多个行版本控制(MVCC)-隔离性

    即在InnoDB存储引擎中MVCC的实现是通过Undo来完成。当用户读取一行记录时,若该记录已经被其他事务占用,当前事务可以通过Undo读取之前的行版本信息,以此实现非锁定读取。

Undo Log的存储结构

  • 回滚段与undo页

InnoDB对Undo Log的管理采用段的方式,也就是回滚段(rollback segment)。每个回滚段记录了1024个Undo Log segment,而在每个Undo Log segment段中进行Undo页的申请。

InnoDB1.1版本之前(不包括1.1版本),只有一个rollback segment,因此支持同时在线的事务限制为1024。虽然对绝大多数的应用来说都已经够用。

从1.1版本开始InnoDB支持最大128个rollback segment,故其支持同时在线的事务限制提高到了128*1024

mysql> show variables like 'innodb_undo_logs'; +------------------+-------+ | Variable_name | Value | +------------------+-------+ | innodb_undo_logs | 128 | +------------------+-------+