Purge流程
Purge功能:
InnoDB由于要支持多版本协议, 因此无论是更新, 删除, 都只是设置记录上的deleted bit标记位, 而不是真正的删除记录. 后续这些记录的真正删除, 是通过Purge后台进程(根据参数srv_n_purge_threads配置, 由下面两个线程中的一个来执行purge: srv_purge_thread(); srv_master_thread())实现的. Purge进程定期扫描InnoDB的undo, 按照先读老undo, 再读新undo的顺序, 读取每条undo record. 对于每一条undo record, 判断其对应的记录是否可以被purge(purge进程有自己的read view, 等同于进程开始时最老的活动事务之前的view, 保证purge的数据, 一定是不可见数据, 对任何人来说), 如果可以purge, 则构造完整记录(row_purge_parse_undo_rec). 然后按照先purge二级索引, 最后purge聚簇索引的顺序, purge一个操作生成的旧版本完整记录.
一个完整的purge函数调用流程如下:
row_purge_step->row_purge->trx_purge_fetch_next_rec->row_purge_parse_undo_rec
->row_purge_del_mark->row_purge_remove_sec_if_poss
->row_purge_remove_clust_if_poss
总结:
purge是通过遍历undo实现的.
purge的粒度是一条记录上的一个操作. 如果一条记录被update了3次, 产生3个old版本, 均可purge. 那么purge读取undo, 对于每一个操作, 都会调用一次purge. 一个purge删除一个操作产生的old版本(按照操作从老到新的顺序).
purge按照先二级索引, 最后聚簇索引的顺序进行.
purge二级索引, 通过构造出的索引项进行查找定位. 不能直接针对某个二级页面进行, 因为不知道记录的存放page.
对于二级索引设置deleted bit为不需要记录undo, 因为purge是根据聚簇索引undo实现. 因此二级索引deleted bit被设置为1的项, 没有记录undo, 仍旧可以被purge.
purge是一个耗时的操作. 二级索引的purge, 需要search_path定位数据, 相当于每个二级索引, 都做了一次index unique scan.
一次delete操作, IO翻番. 第一次IO是将记录的deleted bit设置为1;第二次的IO是将记录删除.
参考资料:
Purge的执行graph