为了保证事务的原子性,设计InnoDB
的大叔引入了undo
日志,undo
日志记载了回滚一个操作所需的必须内容。
在事务对表中的记录进行改动时,才会为这个事务分配一个唯一的事务id
。事务id
值时一个递增的数字。先被分配的id
的事务得到的是较小的事务id
,后被分配id
的事务得到的是较大的事务id。未被分配事务id
的默认为0.聚簇索引记录中有一个trx_id
隐藏列,它代表对这个聚簇索引记录进行改动的语句所在的事务对应的事务id
。
不同的场景有不同类型的undo
日志,比如TRX_UNDO_INSERT_REC
、RRX_UNDO_DEL_MARK_REC
、TRX_UNDO_UPD_EXIST_REC
等。
类型FIL_PAGE_UNDO_LOG
的页面是专门用来存储undo
日志的,我们简称Undo
页面。
在一个事务执行过程中,最多分配4个Undo
页面链表,分别是:
- 针对普通表的
insert undo
链表 - 针对普通表的
update undo
链表 - 针对临时表的
insert undo
链表 - 针对临时表的
update undo
链表
只有真正用到这些链表的时候才会去创建它们
每个undo
页面链表都对应一个Undo Log Segment
。Undo
页面链表的第一个页面中有一个名为Undo Log Segment Header
的部分,专门用来存储关于这个段的一些信息。
同一个事务向一个Undo
页面链表中写入undo日志算是一个组,每个组都以一个Undo Log Header
部分开头。
一个Undo
页面链表如果可以被重用,需要符合下面的条件;
- 该链表中只包含一个
Undo
页面; - 该
Undo
页面已经使用的空间小于整个页面空间的3/4。
每个Rollback Segment Header
页面都对应着一个回滚段,每个回滚段包含1024
个undo slot
,一个undo slot
代表一个Undo
页面链表的第一个页面的页号,目前,InnoDB
最多支持128个回滚段,其中第0
号,第33-127
号回滚段是针对普通表设计的,第1-32
号回滚段是针对临时表设计的。