45 如果事务执行到一半要回滚怎么办?再探undo log回滚日志原理!
探索另外一种日志,就是undo log日志,也就是回滚日志,这种日志要应对的场景,就是事务回滚的场景!
首先大家先思考一个问题,假设现在我们一个事务里要执行一些增删改的操作,那么必然是先把对应的数据页从磁盘加载出来放buffer pool的缓存页里,然后在缓存页里执行一通增删改,同时记录redo log日志,对吧?如下图。

但是现在问题来了,万一要是一个事务里的一通增删改操作执行到了一半,结果就回滚事务了呢?
比如一个事务里有4个增删改操作,结果目前为止已经执行了2个增删改SQL了,已经更新了一些buffer pool里的数据了,但是还有2个增删改SQL的逻辑还没执行,此时事务要回滚了怎么办?看图

如果你要回滚事务的话,那么必须要把已经在buffer pool的缓存页里执行的增删改操作给回滚了。但是怎么回滚呢?毕竟无论是插入,还是更新,还是删除,该做的都已经做了啊!
所以在执行事务的时候,才必须引入另外一种日志,就是undo log回滚日志。
这个回滚日志,他记录的东西其实非常简单,比如你要是在缓存页里执行了一个insert语句,那么此时你在undo log日志里,对这个操作记录的回滚日志就必须是有一个主键和一个对应的delete操作,要能让你把这次insert操作给回退了。
那么比如说你要是执行的是delete语句,那么起码你要把你删除的那条数据记录下来,如果要回滚,就应该执行一个insert操作把那条数据插入回去。
如果你要是执行的是update语句,那么起码你要把你更新之前的那个值记录下来,回滚的时候重新update一下,把你之前更新前的旧值给他更新回去。
如果你要是执行的是select语句呢?不好意思,select语句压根儿没有在buffer pool里执行任何修改,所以根本不需要undo log!
好,所以我们来看下图,其实你在执行事务期间,这个undo log日志是至关重要的,没有他,你根本都没办法回滚事务!
