undo日志将事务回滚原理

662 阅读2分钟

「这是我参与11月更文挑战的第10天,活动详情查看:2021最后一次更文挑战

InnoDB是现在MySQL用的比较多的存储引擎,使用它的原因,个人觉得是因为它支持事务,在项目中,基本上对于数据修改都会用到事务,在同一个事务中,都会对多张表进行修改,如果某一张表执行失败了,就需要将整个事务进行回滚?那么MySQL是如何将已更新的数据进行回滚的呢?保证事务的原子性,一个事务操作要么全部成功 ,要么全部失败。 大家都知道MySQL在更新数据的时候,会先将原来的数据记录到Undo日志文件中,然后在将BufferPool里的缓存页执行修改,然后记录Redo Log日志,等到时机成熟的时候再将BufferPool中的脏页刷到磁盘中。 当执行一半事务的时候,如果需要回滚事务,那么就必须要把已经在buffer pool的缓存页执行的操作给回滚,那么在回滚数据的时候,就需要从undo log中找到对应的回滚日志来将现在的数据恢复到事务操作前的数据。

UndoLog回滚数据的大致原理

UndoLog回滚数据的基本原理就是在操作数据的时候把旧数据记录下来,然后需要回滚的时候对当前操作生成相反的语句执行达到还原数据的目的。

  • INSERT语句:在undo log日志里,对这个操作记录的回滚日志就必须是有一个主键和一个对应的DELETE操作,让能把这次INSERT操作给回退,所以我们采用自增的主键,当插入数据失败后,下一次的主键就不是这次回滚的主键
  • DELETE语句:将删除的那条数据记录下来,如果要回滚,执行一个INSERT操作把那条数据插入回去
  • UPDATE语句:把更新之前的那个值记录下来,回滚的时候重新UPDATE,把更新前的旧值给重新更新回去
  • SELETE语句:没做数据修改,不记录日志

回滚日志格式

每种日志都有具体对应的格式,下面以INSERT语句来看下undo log日志长什么样子?

  • 日志的开始位置
  • 主键的各列长度和值:插入数据的主键的每个列,它的长度,具体的值是多少,如果没有设置主键,那么久会用ROW_ID作为隐藏列做主键
  • 表id:数据表的ID,可以理解为表名
  • undo log日志编号
  • undo log日志类型:INSERT语句类型为:TRX_UNDO_INSERT_REC
  • 日志的结束位置

image.png