这篇来小小的浅析一下undo log😁~~
概念
redo log属于逻辑日志, 记录了事务的行为,可以很好的对页进行“重做”操作,但是事务有时候还需要进行回滚操作,这时候就需要undo。
与reod log不同,undo log存放在数据库内部的一个特殊段(segment)中,这个段就称为undo段。undo段位于共享表空间中。undo log
主要存储的也是逻辑日志,比如我们要insert
一条数据了,那undo log
会记录的一条对应的delete
日志。我们要update
一条记录时,它会记录一条对应相反的update记录。
除了回滚操作,undo的另一个作用是MVCC,即在InnoDB中MVCC的实现是通过undo来完成的,当用户读取一行记录时,若该记录已经被其他事务占用,当前事务可以通过读取之前的行版本信息,以此实现非锁定读取。
注意:undo log会产生redo log,也就是undo log的产生会伴随着redo log的产生,这是因为undo log也需要持久性的保护。
undo存储管理
innodb存储引擎对undo的管理采用段的方式。innoDB 中有rollback segment称为回滚段,每个回滚段中有1024个undo log segment。
在以前老版本,只支持1个rollback segment,这样就只能记录1024个undo log segment。后来1.1版本之后可以支持128个rollback segment,即支持128*1024个undo操作,还可以通过变量 innodb_undo_logs (5.6版本以前该变量是 innodb_rollback_segments )自定义多少个rollback segment,默认值为128。
undo log 在事务开始前产生。
事务在undo log sement 分配页并写入undo log 的这个过程同样需要写入redo log。当事务提交时,InnoDB存储引擎会做一下两件事:
- 将undo log放入列表中,以供之后的purge操作。
- 判断undo log所在的页是否可以重用(undo页使用空间小于3/4),若可以分配给下一个事务使用。之后的undo log 记录在前面的undo log 之后。
事务提交后不能马上删除undo log 以及undo log 所在的页,因为可能还有其他事务需要通过undo log 来得到行记录之前的版本。故事务提交时将undo log 放入一个链表中,是否可以最终删除undo log 及undo log 所在的页由purge线程来判断。
purge操作涉及磁盘的离散读取操作,是一个比较缓慢的过程。
undo log 分为insert undo ,update undo。
insert log是指在insert操作中产生的undo log ,因为insert操作只对事务本身可见,对其他事务不可见(隔离性),所以该insert undo log 可以在事务提交后直接删除,不需要purge 操作。而update undo log记录的是对delete和update 操作产生的undo log ,该undo log可能需要提供MVCC机制,因此不能直接删除,需要purge来删除 。
这里还需记录的一个知识点:delete操作并不直接删除记录,而只是将记录标记为已删除(delete flag=1),最后的删除是purge完成的。update操作分两部分完成,首先将原主键记录标记为已删除,产生一个类型为DEL的undo log ,之后插入一条新纪录,产生一条类型为INSERT的undo log。
undo log 和 redo log 的区别
参考 :
1.《MySQL技术内幕--InnoDB存储引擎》
2. https://www.cnblogs.com/f-ck-need-u/archive/2018/05/08/9010872.html#auto_id_0