设为首页 加入收藏

TOP

数据库原理 - 序列4 - 事务是如何实现的? - Redo Log解析(续)(三)
2019-09-17 18:52:06 】 浏览:91
Tags:数据库 原理 序列 事务 如何 实现 Redo Log 解析
了磁盘,干净页也可能重新写入了一次。并且未提交事务T3、T4、T5对应的Page数据也写入了磁盘。接下来,就是要对T3、T4、T5回滚。

阶段3:进行Undo
在阶段1,我们已经找出了未提交事务集合{T3,T4,T5}。从最后一条日志逆向遍历,因为每条日志都有一个prevLSN字段,所以可以沿着T3、T4、T5各自的日志链一直回溯,最终直到T3的第一条日志。
所谓的Undo,是指每遇到一条属于T3、T4、T5的Log,就生成一条逆向的SQL语句来执行,其执行对应的Redo Log是Compensation Log Record(CLR),会在Redo Log尾部继续追加。所以对于Redo Log来说,其实不存在所谓的“回滚”,全部是正向的Commit,日志只会追加,不会执行“物理截断”之类的操作。
要生成逆向的SQL语句,需要记录对应的历史版本数据,这点将在分析Undo Log的时候详细解释。
这里要注意的是:Redo的起点位置和Undo的起点位置并没有必然的先后关系,图中画的是Undo的起点位置小于Redo的起点位置,但实际也可以反过来。以为Redo对应的是所有脏页的最小LSN,Undo对应的是所有未提交事务的起始LSN,两者不是同一个维度的概念。
在进行Undo操作的时候,还可能会遇到一个问题,回滚到一半,宕机,重启,再回滚,要进行“回滚的回滚”。
如图6-17所示,假设要回滚一个未提交的事务T,其有三条日志LSN分别为600、900、1000。第一次宕机重启,首先对LSN=1000进行回滚,生成对应的LSN=1200的日志,这条日志里会有一个字段叫作UndoNxtLSN,记录的是其对应的被回滚的日志的前一条日志,即UndoNxtLSN = 900。这样当再一次宕机重启时,遇到LSN=1200的CLR,首先会忽略这条日志;然后看到UndoNxtLSN = 900,会定位到LSN=900的日志,为其生成对应的CLR日志LSN=1600;然后继续回滚,LSN=1700的日志,回滚的是LSN=600。
这样,不管出现几次宕机,重启后最终都能保证回滚日志和之前的日志一一对应,不会出现“回滚嵌套”问题。
![在这里插入图片描述](https://img-blog.csdnimg.cn/20190412104354375.?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L2NodW5sb25neXU=,size_16,color_FFFFFF,t_70)
图6-17 回滚过程中出现宕机后再次重启回滚

到此为止,已经对事务的A(原子性)和D(持久性)有了一个全面的理解,接下来将讨论I的实现。在此先对Redo Log做一个总结:
(1) 一个事务对应多条Redo Log,事务的Redo Log不是连续存储的。
(2) Redo Log不保证事务的原子性,而是保证了持久性。无论提交的,还是未提交事务的日志,都会进入Redo Log。从而使得Redo Log回放完毕,数据库就恢复到宕机之前的状态,称为Repeating History。
(3) 同时,把未提交的事务挑出来并回滚。回滚通过Checkpoint记录的“活跃事务表”+ 每个事务日志中的开始/结束标记 + Undo Log 来实现。
(4) Redo Log具有幂等性,通过每个Page里面的pageLSN实现。
(5) 无论是提交的、还是未提交的事务,其对应的Page数据都可能被刷到了磁盘中。未提交的事务对应的Page数据,在宕机重启后会回滚。
(6) 事务不存在“物理回滚”,所有的回滚操作都被转化成了Commit。

首页 上一页 1 2 3 下一页 尾页 3/3/3
】【打印繁体】【投稿】【收藏】 【推荐】【举报】【评论】 【关闭】 【返回顶部
上一篇MySQL系列--4.使用Python3访问数.. 下一篇Oracle截取JSON字符串内容

最新文章

热门文章

Hot 文章

Python

C 语言

C++基础

大数据基础

linux编程基础

C/C++面试题目