文章目录
1、前言
2、undo日志
2.1 作用
2.2 举例
2.3 原理
3、redo日志
3.1 作用
3.2 举例
3.3 原理
1、前言
为了实现事务的原子性和持久性,mysql引入了undo和redo日志(即undo log和redo log)。本篇博客来讲解下undo和redo的概念,以及mysql如何利用undo和redo进行异常宕机恢复。
2、undo日志
2.1 作用
undo日志记录的是修改前的值
2.2 举例
事务A要将字段age的值由原来的1修改为2,要将name的值由原来的Alice修改为Bob,undo日志记录的过程表如下:
假设现在数据库出现了宕机的问题,分为两种情况:
如果在上表第三步之前数据库挂了,则最终数据和日志均为原数据;
如果第三步及以后出现异常,则undo已经记录了原来的值,则可以利用undo日志将数据恢复为原数据。
2.3 原理
当事务提交之后,undo不会被马上删除,而是放入待删除队列,由purge线程来判断是否删除和处理。
在mysql5.6之前,undo只存在于共享表空间中,之后的版本中,则可以配置为独立的文件。
undo内部默认128个回滚段槽(rseg slot),每个rseg slot内部有1024个回滚段(rollback segment)。其中:
slot0——共1个,预留给系统表空间
slot1~slot31——共31个,预留给临时表空间
slot32~slot127——共96个,预留给undo独立表空间
由于undo日志会被清理掉,不能保证事务的持久性,因此才需要引入redo日志来保证事务的持久性。
3、redo日志
3.1 作用
redo日志记录的是修改后最新的数据和冗余的undo日志
3.2 举例
事务B要将字段age的值由原来的1修改为2,要将name的值由原来的Alice修改为Bob,redo日志记录的过程表如下:
其中,redo日志必须先于数据写入磁盘(即步骤8和步骤9的顺序不能改变)。因为如果不这样,在数据提交之后再写redo日志,一旦redo日志的写入过程出现异常,将无法保证持久性。
记录redo日志时,先记入redo log buffer,最后再一起写入磁盘,这样可以减少IO,提升性能。
另外,未提交的事务和回滚了的事务也会计入redo日志。
现在假设:如果上面事务B回滚(当做新的事务C),则redo记录的过程表如下:
3.3 原理
mysql的恢复策略是:
恢复时,先根据redo重做所有事务(包括未提交和回滚了的)
再根据undo回滚未提交的事务。
如上,如果事务B异常未提交事务就宕机,恢复时,先根据redo日志将数据恢复为age=2&name=Bob,然后再根据undo记录的age=1&name=Alice将数据恢复如初。
如果事务C异常未提交事务就宕机,恢复时,根据redo日志,可以直接恢复至age=1&name=Alice的初始状态。
redo日志会随着时间推移而越来越大,为了提升redo的恢复性能,引入了checkpoint机制,在恢复的时候,只需要从checkpoint的位置往后恢复即可。