MySQL 事务之 undo log
上面说的 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_id
和 old_roll_pointer
,也就是在删除之前,要先将该记录的旧的事务 id 和 roll_pointer
记录到 undo 日志里,这样该记录的 undo 日志就能形成一个版本链:
还有一个索引各列信息的内容,主要是在 purge 阶段使用的
Update 对应的 undo 日志
分为不更新主键和更新主键两种情况
在不更新主键的情况下,undo 日志的格式和 delete 的时候差不多,也会记录旧的 trx_id
和 roll_pointer
,会记录被更新列的更新前的信息,如果被更新的列包含索引,还会记录索引列各列信息。
在更新主键的情况下,分为先对原记录 delete 再 insert 两个步骤,也就是会产生两条 undo 日志,这两条 undo 日志的格式上面都说过了。
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论