MySQL 事务之 undo log

上面说的 redo 日志主要是满足事务持久性的要求。而事务还有一个要求就是原子性,也就是执行过程中如果出错了,或者手动 ROLLBACK,需要把已经修改的地方都改回事务开始前的状态。这个时候就要靠 undo 日志(undo log)了,和 redo 日志类似,undo 日志就是把在事务执行过程中的增、删、改操作都记下来(查询操作不需要记录 undo 日志)。

MySQL 会为涉及了增删改操作的事务分配一个 id 叫做事务 id,这个 id 是全局递增的,类似表中的自增 id。事务 id 会存放在记录中,最开始讲记录的行格式时提到过:

MySQL 事务之 undo log

除了事务 id 外,记录里面的 roll_pointer 也和事务有关,记录了指向对应的undo日志的指针。

Insert 对应的 undo 日志

MySQL 事务之 undo log

上面字段很多不必全都理解,主要有:

  • undo type:该 undo 日志的类型,这里 insert 操作对应的当然是 insert 类型
  • undo no:undo日志的编号,在一个事务的执行过程中,undo 日志从 0 开始编号
  • table id:insert操作的表的 table id
  • 主键各列信息:这里只需要记录主键信息就行,因为回滚的时候,只需要定位到主键,然后进行删除操作就行了,会顺带把二级索引的记录也删除掉

Delete 对应的 undo 日志

一个页面中的记录被删除之后,会先从正常记录的链表转移到垃圾链表中等待回收/重用,同时记录中的delete_mask字段置为1。而在事务提交之前,仅仅会将delete_mask字段置为1,还不会将这条记录移入垃圾链表:

MySQL 事务之 undo log

事务提交之后,会有专门的后台线程来把记录删掉,这个过程称为 purge。

删除操作对应的 undo 日志格式如下:

MySQL 事务之 undo log

需要关注的主要是:

old_trx_idold_roll_pointer,也就是在删除之前,要先将该记录的旧的事务 id 和 roll_pointer 记录到 undo 日志里,这样该记录的 undo 日志就能形成一个版本链:

MySQL 事务之 undo log

还有一个索引各列信息的内容,主要是在 purge 阶段使用的

Update 对应的 undo 日志

分为不更新主键和更新主键两种情况

在不更新主键的情况下,undo 日志的格式和 delete 的时候差不多,也会记录旧的 trx_idroll_pointer,会记录被更新列的更新前的信息,如果被更新的列包含索引,还会记录索引列各列信息。

在更新主键的情况下,分为先对原记录 delete 再 insert 两个步骤,也就是会产生两条 undo 日志,这两条 undo 日志的格式上面都说过了。

以上是 MySQL 事务之 undo log 的全部内容, 来源链接: utcz.com/z/264434.html

回到顶部