上篇文章说了redo日志是为了保证持久化,提高效率而产生的的,buffer pool有一个inndb buffer poll size来控制大小,并且默认128m,大于一个1g可以设置多个,但是每次同步持久化是随机I.O,redo log也有日志池,把随机io优化为顺序io,并且占用的地方小。
Undo日志
如何保证事务里的原子性,当数据执行到一半需要回滚,或者数据库发生宕机,这时候就需要保证事务原子性,所以回滚应该只有发生新增,修改,删除时候才考虑,select并没有回滚操作。
当在一个事务里,对数据做了改动,这时候就会给事务生成一个唯一的事务ID,生成的机制也跟row_id类似,会有一个全局的max_trx_id来维护,每次有新的数据就自增1。
这里除了trx_id外,还有roll_pointer,他本质上就是一个指针,指向对应的undo日志。
删除的时候如何记录的,这里比较特殊,之前我们说过页的page header存着delete mark,删除状态,在没提交之前,是先把状态修改,为什么会有这一步呢,是为了实现mvcc的功能。第二步提交之后,才会真的删除,这时候会把数据加入垃圾链表。这时候delete删除之后,会有一个old_roll_pointer指向之前的insert,组成版本链。
Update更新的时候分为两种情况,
一种是不更新主键的情况,这时候又分为更新的列长度是否发生变化,未发生,则就地更新,如果长度变化了,则会先删除之前的数据,再新增,重排序。
一种是更新主键的情况,会对该记录先进行delete mark操作,之后再插入新的数据,也就是说,每次都会产生两条undo log。
我们前面说过表空间是很多页组成,fil_page_index存储聚簇索引二级索引,
fil_page_type_fsp_hdr存储表空间头部信息,这里存的就是fil_page_undo_log。
Undo日志是分为两大类,一类是可以提交直接删除,一类还是为了mvcc服务。在undo日志中,每个页分类不同的链表连接起来,insert undo,update undo链表。