前言
为什么MySQL InnoDB需要Purge操作?明确这个问题的答案,首先还得从InnoDB的并发机制开始。为了更好的支持并发,InnoDB的多版本一致性读是采用了基于回滚段的的方式。另外,对于更新和删除操作,InnoDB并不是真正的删除原来的记录,而是设置记录的delete mark为1。因此为了解决数据Page和Undo Log膨胀的问题,需要引入purge机制进行回收。下面我们来描述下purge整个过程。(代码分析基于MySQL 5.7)
Purge数据产生的背景
- Undo log和Undo history list
- Mark deleted数据
Undo log
Undo log保存了记录修改前的镜像。在InnoDB存储引擎中,undo log分为:
- insert undo log
- update undo log
insert undo log是指在insert操作中产生的undo log。由于insert操作的记录,只是对本事务可见,其他事务不可见,所以undo log可以在事务提交后直接删除,而不需要purge操作。
update undo log是指在delete和update操作中产生的undo log。该undo log会被后续用于MVCC当中,因此不能提交的时候删除。提交后会放入undo log的链表,等待purge线程进行最后的删除。
下面列出了undo log类型,后续在purge工作线程的时候会针对性的讲述不同的处理方式:
-
从表中删除一行记录
TRX_UNDO_DEL_MARK_REC (将主键记入日志),在删除一条记录时,并不是真正的将数据从数据库中删除,只是标记为已删除。 -
向表中插入一行记录
TRX_UNDO_INSERT_REC (仅将主键记入日志)
TRX_UNDO_UPD_DEL_REC (将主键记入日志) 当表中有一条被标记为删除的记录和要插入的数据主键相同时, 实际的操作是更新这个被标记为删除的记录。 -
更新表中的一条记录
TRX_UNDO_UPD_EXIST_REC (将主键和被更新了的字段内容记入日志)
TRX_UNDO_DEL_MARK_REC和TRX_UNDO_INSERT_REC,当更新主键字段时,实际执行的过程是删除旧的记录然后,再插入一条新的记录。