赞
踩
undo log 存储在类型为 FIL_PAGE_UNDO_LOG 页中。 可以从系统表空间中分配空间,也可以从 undo tablespace 中分配空间。 FIL_PAGE_UNDO_LOG 类型页主要分为四部分:
INSERT
对应的 undo log 记录格式插入区分乐观插入、悲观插入,
不管如何,是将一条记录插入。 它对应的回滚操作,就是删除这条插入的记录,TRX_UNDO_INSERT_REC:
INSERT
语句的 undo log。information_schema.INNODB_TABLES
中查询到。INSERT
相对应的回滚日志是删除插入的记录,所以这里要记录的信息需要包含如何定位到这条记录。其中,start of record 和 end of record 是两个指针,指向了 undo log 记录开始、结束的位置。
DELETE
对应的 undo log 记录格式在介绍 记录 和 页 时有提到,数据页中所有的记录通过 next_record 串联起来,形成一个链表。 所有的被标记为删除(即 delete_mask 为1)的记录也会通过 next_record 串联起来,形成垃圾链表。 数据页的 Page Header 中有一个 PAGE_FREE 属性,指向垃圾链表的头部。
首先,我们要先搞明白 DELETE
语句的执行过程。删除分为两个阶段:
delete mask 阶段对应的 undo log 类型为 TRX_UNDO_DEL_MARK_REC:
UPDATE
对应的 undo log 记录格式UPDATE
语句的处理方式根据是否更新主键分为两种不同的方案:
不更新主键。 根据是否改变记录的大小,又可以进一步分为:
DELETE
中分两阶段的删除。 与 purge 阶段不同的事,并非是某个特定线程去删除,而是由用户线程同步删除。针对不更新主键的情况,undo log 类型为 TRX_UNDO_UPD_EXIST_REC(省略了 end of record 之类的共有的信息):
更新主键。分为两步处理:
所以,这种情况会产生两条 undo log 记录。
在学习 InnoDB 行记录格式时,我们知道在聚簇索引中记录的数据部分 InnoDB 会自动插入三列:DB_ROW_ID\DB_TRX_ID\DB_ROLL_PTR。 其中 DB_ROW_ID 不是必需的,只在没有指定主键且没有唯一列时插入。 其余两列与事务及一致性读视图相关:
对某条记录的每次修改(UPDATE
、DELETE
),都会在 undo log 中记录一个旧版本,旧版本中也包括 DB_ROLL_PTR 列、事务 ID 列。 因此,undo log 中记录的所有版本会形成一个链表,值越旧,它就在链中越靠近末尾的位置,该记录的最新值,记录在聚簇索引中的记录上。
我们借用《MySQL 是怎样运行的:从根儿上理解 MySQL》中的一幅图,加深下对版本链的理解。
图中所示的是插入、并删除一条记录后,形成的版本链。
在读未提交事务隔离级别下,直接读取记录的最新版本即可; 在串行级别下,需要使用锁来保证。 所以,版本链主要应用于读提交和可重复读事务隔离级别。 它要解决的核心问题就是,版本链中的哪些版本是当前事务可见的。
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。