MySQL 事务之 undo log

发布于 2022-01-19 12:42:42 字数 2220 浏览 1186 评论 0

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

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

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

Insert 对应的 undo 日志

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

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

Delete 对应的 undo 日志

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

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

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

需要关注的主要是:

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

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

Update 对应的 undo 日志

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

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

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

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。
列表为空,暂无数据

关于作者

JSmiles

生命进入颠沛而奔忙的本质状态,并将以不断告别和相遇的陈旧方式继续下去。

0 文章
0 评论
84961 人气
更多

推荐作者

已经忘了多久

文章 0 评论 0

15867725375

文章 0 评论 0

LonelySnow

文章 0 评论 0

走过海棠暮

文章 0 评论 0

轻许诺言

文章 0 评论 0

信馬由缰

文章 0 评论 0

    我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
    原文