目录
1、事务回滚
例如:一个事务里有
4
个增删改操作,结果目前为止已经执行了
2
个增删改
SQL
了,已经更新了一些
buffer pool里的数据了,但是还有
2
个增删改
SQL
的逻辑还没执行,此时事务要回滚了怎么办?
如果要回滚事务的话,那么必须要把已经在buffer pool的缓存页里执行的增删改操作给回滚。
回滚日志记录的内容:
- 你要是在缓存页里执行了一个insert语句,那么此时你在undo log日志里,对这个操作记录的回滚日志就必须是有一个主键和一个对应的delete操作,要能让你把这次insert操作给回退。
- 你要是执行的是delete语句,那么起码你要把你删除的那条数据记录下来,如果要回滚,就 应该执行一个insert操作把那条数据插入回去。
- 你要是执行的是update语句,那么起码你要把你更新之前的那个值记录下来,回滚的时候重新update一下,把你之前更新前的旧值给他更新回去。
- 你要是执行的是select语句呢?不好意思,select语句压根儿没有在bufer pool里执行任何修改,所以根本不需要undo log!
总结:
undo log回滚日志的作用:就是你执行事务的时候,里面很多INSERT、 UPDATE和DELETE语句都在更新缓存页里的数据,但是万一事务回滚,你必须有每条SQL语句对应的undo log回滚日志,根据回滚日志去恢复缓存页里被更新的数据。
比如你执行了INSERT
语句,那么你的
undo log
必须告诉你插入数据的主键
ID
,让你在回滚的时候可以 从缓存页里把这条数据给删除了;
如果你执行了DELETE
语句,那么你的
undo log
必须记录下来被删除的数据,回滚的时候就得重新插入一条数据;
如果你执行了UPDATE
语句,那么你必须记录下来修改之前的数据,回滚的时候就得把数据给更新回去
![](https://i-blog.csdnimg.cn/blog_migrate/6519efa6e57a594ca0e2592aff484d42.png)
2、INSRET语句的undo log回滚日志长什么样?
INSERT语句的
undo log
的类型是
TRX_UNDO_INSERT_REC
,这个
undo log
里包含了以下一些东西:
- 这条日志的开始位置
- 主键的各列长度和值
- 表id
- undo log日志编号
- undo log日志类型
- 这条日志的结束位置
- 一条日志必须得有自己的一个开始位置。
- 那么主键的各列长度和值是什么意思?大家都知道,你插入一条数据,必然会有一个主键!
- 如果你自己指定了一个主键,那么可能这个主键就是一个列,比如id之类的,也可能是多个列组成的一 个主键,比如“id+name+type”三个字段组成的一个联合主键,也是有可能的。 所以这个主键的各列长度和值,意思就是你插入的这条数据的主键的每个列,他的长度是多少,具体的值是多少。即使你没有设置主键,MySQL自己也会给你弄一个row_id作为隐藏字段,做你的键。
- 表id,这个就不用多说了,你插入一条数据必然是往一个表里插入数据的,那当然得有一个表id,记录下来是在哪个表里插入的数据了。
- undo log日志编号,这个意思就是,每个undo log日志都是有自己的编号的。而在一个事务里会有多个SQL语句,就会有多个undo log日志,在每个事务里的undo log日志的编号都是从0开始的,然后依次递增。
- undo log日志类型,就是TRX_UNDO_INSERT_REC,insert语句的undo log日志类型就是这个东西。
- undo log日志的结束位置,这个自然也不用多说了,他就是告诉你undo log日志结束的位置是 什么。
万一要是你现在在buffffer pool的一个缓存页里插入了一条数据了,执行了insert语句,然后你写了一条 上面的那种undo log,现在事务要是回滚了,你直接就把这条insert语句的undo log拿出来。然后在undo log里就知道在哪个表里插入的数据,主键是什么,直接定位到那个表和主键对应的缓存页,从里面删除掉之前insert语句插入进去的数据就可以了,这样就可以实现事务回滚的效果了!