一、redo日志
原先A=1。现在做更新操作A=3。
为什么要有redo?不能直接把数据从内存buffer pool中写到磁盘页中吗?
一是每次操作都写磁盘太慢了,尤其还是零散的写,批量写入比单条写入好。
二是redo虽然也每次操作都写入磁盘,但是顺序写。
redo流程
内存redo buffer 记录A=3;内存buffer pool中记录A=3;磁盘redo file 记录A =3。一定的时机(redo满了等),把内存buffer pool的A=3刷新到磁盘页中A=3(并不是酱磁盘redo file的A=3刷新到磁盘页中,只有宕机的时候,内存buffer pool的A=3丢失了,才从磁盘redo file中刷新到磁盘页中,做恢复)
如何保证redo的持久化?
a.内存redo buffer-> b. 操作系统内存 os cache-> c. 磁盘redo file。
a->b->c是innodb默认的,每个sql操作都会a->b->c。就是性能比较慢。
可以调innodb参数。可以只有a,操作系统或mysql宕机会丢失数据,但是性能快。也可以只有a->b,mysql宕机会丢失数据,但是性能快。
二、undo日志
原先A=1。现在做更新操作A=3。
为什么要有undo日志?
一是用于回滚。都是记录反向的操作,用于回滚。如insert操作,则记录delete
二是用于MVCC
如何记录undo?
原先A=1
开启事务a。更新A=3。将A=1的行,改为A=3。然后开辟undo,undo记录原先的A=1,事务id为a,指针指向原本的位置,即现在为A=3(原本为A=1)的行。
开启事务b。更新A=4。将A=3的行,改为A=4。记录undo,undo记录原先的A=3,事务id为b,指针指向上面的undo,即指向事务id为a、A=1的记录
事务a要回滚。则根据undo日志进行操作,拿出undo记录(即A=1,事务为a的记录即可)
如何用于MVCC?
如果事务c是insert操作(undo记录delete),则其他事务的d、e自然不需要看见,事务c提交后,undo的delete记录可以直接删除。
但是对于update操作,其他事务可能会读取到,事务c提交后,undo记录不可删除,事务d、e的readView可能读取的是事务c的数据,所以数据c的记录还不可以删除,现放着,由purge线程删除。
三、redo和undo
都是恢复日志,都是innodb层的日志
redo是物理日志,记录的是磁盘页数据变化;undo是逻辑日志,记录的是每个操作的反向,因为会有多个事务并发操作,所以不一定能恢复到事务开始的状态
参考: