1

mysql 自动的故障安全恢复详解(acsr) -利来国际app

陈家睿 2021-11-30
636

acsr(auto crash safey recovery)自动的故障安全恢复


更新操作

在一行数据被更新的时候

1、在使用begin开启事务时,会先给.ibd文件中分配一个txid号和lsn号,假设为tx_01与lsn1001
2、在update执行时,mysql会找到需更新数据的数据页,并将其内容加载到data buffer pool中,由dbwr(double write)线程记录变更数据页的内容,并且记录好txid和更新lsn号,此时将产生脏页与脏数据
3、使用logbwr(log double write)线程,将更新前的数据页变化内容与txid号以及lsn号记录到undo log buffer中
4、使用logbwr(log double write)线程,将更新后的数据页变化内容与txid号以及lsn号记录到redo log buffer中
    现在,基于wal原则为了应对用户进行rollback操作,logbwr(log double write)线程会将undo log buffer中的内容全部写入到undo_log即ibdata1(mysql5.7版本undo_log仍然存在于共享表空间中)文件中


commit操作

现在我们基于上面begin后发生的情况执行commit操作,内部会做以下的3件事:

1、执行commit操作,基于wal原则,logbwr线程会先将redo log buffer中记录的日志信息写入redo_log文件中,在日志信息完全写入redo_log即ib_logfile文件后,会对该日志打上commit的标志
2、触发ckpt,将内存数据页更新到磁盘中,并且更新磁盘数据页文件userinfo.ibd中原有的lsn号,让其与redo_log文件中的lsn号保持一致
3、清空内存undo log buffer、data buffer pool、redo log buffer以及磁盘上undo_log中的数据

可以看到整个事务提交的过程是先写日志,再落盘写数据。

其实redo log buffer将数据刷新到redo_log文件中的策略除开自己手动执行commit外还有另一种情况。

在多任务时,其他线程commit操作也可能会导致整个redo log buffer的刷新,刷新的redo_log文件中会对本线程提交的事务打上nocommit的标记。

其实这种现象取决于data buffer pool中存储的数据量占据data buffer pool总量的多少来决定,一般来说如果占据到70%左右就会触发该现象,我们可以对其进行手动设置,但一般来说保持默认值即可。


回滚

现在我们基于上面begin后发生的情况执行rollback操作,内部会做以下的2件事:
1、执行rollback操作,logbwr线程会将undo log buffer中的数据重写回到data buffer pool中,并且会把内存脏页数据恢复到最开始的值,然后对lsn号进行回滚更正
2、清空内存undo log buffer、redo log buffer以及磁盘上undo_log中的数据


前滚

mysql : 在启动时,必须保证redo日志文件和数据文件lsn必须一致, 如果不一致就会触发csr,最终保证一致
情况一:
我们做了一个事务,begin;update;commit.
1.在begin ,会立即分配一个txid=tx_01.
2.update时,会将需要修改的数据页(dp_01,lsn=1001),加载到data buffer中
3.dbwr线程,会进行dp_01数据页修改更新,并更新lsn=1002
4.logbwr日志写线程,会将dp_01数据页的变化 lsn txid存储到redobuffer
5. 执行commit时,lgwr日志写线程会将redobuffer信息写入redolog日志文件中,基于wal原则,
在日志完全写入磁盘后,commit命令才执行成功,(会将此日志打上commit标记)
6.假如此时宕机,内存脏页没有来得及写入磁盘,内存数据全部丢失
7.mysql再次重启时,必须要redolog和磁盘数据页的lsn是一致的.但是,
此时dp_01,txid=tx_01
磁盘是lsn=101,dp_01,txid=tx_01,redolog中lsn=102
mysql此时无法正常启动,mysql触发csr.在内存追平lsn号,触发ckpt,将内存数据页
更新到磁盘,从而保证磁盘数据页和redolog lsn一值.这时mysql正常启动
以上的工作过程,我们把它称之为基于redo"前滚操作"
 
log sequence number: 当前系统最大的lsn号
log flushed up to:当前已经写入redo日志文件的lsn
pages flushed up to:已经将更改写入脏页的lsn号
last checkpoint at就是系统最后一次刷新buffer pool脏中页数据到磁盘的checkpoint
以上4个lsn是递减的,即: lsn1>=lsn2>=lsn3>=lsn4.
比对redo的lsn和数据页的lsn,如果数据页的lsn比redo小,
那么就需要通过redo对数据页进行重做。


前滚回滚

如果在commit操作过程前发生了宕机,此时内存中的数据会全部丢失,但是恰好宕机前一秒由于其他线程的commit操作导致了整个redo log buffer的自动刷新,此时redo_log文件中已经写入了刚刚本线程操作事务的txid号以及lsn号且标记此次操作是nocommit状态的情况下重启mysqld.service服务时将会产生如下情况

1、重启mysqld.service服务,发现redo_log中记录的lsn号和ibd文件中记录的lsn号不一致,将触发csr自动故障恢复机制的第一个阶段,前滚操作开始
2、通过redo_log文件中的变更记录日志,在内存数据页中恢复更改的数据
3、发现redo_log文件中的事务标记是nocommit,将触发csr自动故障恢复的第二个阶段,回滚操作开始
4、通过undo log文件中的信息记录,在内存数据页中对前滚数据进行更改
5、使用logbwr线程,将更新的数据页变化信息与txid以及lsn号记录到redo log buffer中
6、此时logbwr线程会先将redo log buffer中记录的信息写入到redo_log文件中,在日志信息完全写入log file即ib_logfile文件后,会对该日志打上commit标记
7、触发ckpt,将内存数据页更新到磁盘文件ibd中
8、回滚工作完成,redo_log中记录的lsn号与ibd中记录的lsn号一致,mysqld.service服务正常启动
最后修改时间:2021-12-01 07:35:54
「喜欢文章,快来给作者赞赏墨值吧」
1人已赞赏
【利来手机国际的版权声明】本文为墨天轮用户原创内容,转载时必须标注文章的来源(墨天轮),文章链接,文章作者等基本信息,否则作者和墨天轮有权追究责任。如果您发现墨天轮中有涉嫌抄袭或者侵权的内容,欢迎发送邮件至:[email protected]进行举报,并提供相关证据,一经查实,墨天轮将立刻删除相关内容。

文章被以下合辑收录

评论