悟已往之可谏—undo log

undo log记录我们对记录的一些改动。所以读记录是不会写入这个日志的,只有增删改才可以。分为两种类型,insert操作是其一,非insert操作是其二。因为insert的log在事务提交后就可以删除了,而非insert 类型的undo log还要为MVCC而服务。

insert 对应undo log

insert操作对应的undo log中记录主键就可以了。记录中有一个roll_pointer属性指向对应的undo log。

delete 对应undo log

delete因为IO成本的考虑,并不会在执行delete后就直接彻底删除,这里的彻底删除可以看成是把该条记录加入垃圾链表。delete操作一般分为两步,第一步是先设置delete_mask标志位,第二步在事务提交后进行,即将记录加入垃圾链表。

因为提交之后不会再回滚,所以事实上,undo log中只会记录第一步。

delete操作对应的undo log中有一个叫old roll_pointer,删除之前该记录对应的roll_pointer的指向值会被放到这里。

所以假设现在我们有一个先增后删的操作,那么,undo log日志将会形成一个链表,链表头是当前记录记录,该记录中的roll_pointer指向delete操作对应的undo log,紧接着该undo log中的old roll_pointer又指向添加操作对应的undo log。

update 对应undo log

非主键的更新

此时使用的是 update对应的 undo log。该日志跟delete 的undo log也有old roll_pointer属性,记录着之前记录的roll_pointer属性对应的undo log。该log同时还会记录被更新列更新前的信息。

根据更新的列的值跟更新之前占用空间是否发生了变化而有所区分。

  1. 更新前后占用空间没变,直接就地更新

  2. 更新前后占用空间发生了变化,先把原纪录删除,注意这里是彻底删除,即同步完成我们上边说的delete的两个步骤,然后紧接着插入新的记录。

主键更新

此时一条更新需要两条undo log,分为两步

  1. 首先执行delete mask的标记,即此时使用的是delete的undo log

  2. 添加新纪录,记录insert 的undo log

undo log日志总结

undo log主要是用来配合回滚使用,回滚所需的东西都在undo log中记录起来了。同时在MVCC中也有它的身影,每次对记录进行改动都会记录一条undo log,每条undo log都有一个roll_pointer属性,这些log就串起来形成版本链,最开头的节点就是当前记录的最新的值。每个版本都有事务id,MVCC就是根据事务id大小来判断事务可见的。

个人公众号

你可能感兴趣的:(数据库,mysql,java)