Redo日志
undo日志有一个潜在的问题,即我们在将书屋改变的所有数据写到磁盘前不能提交该事务。有时,如果让数据库修改暂时只存在于主存中,我们可以节省磁盘IO;只要在崩溃发生时有日志可以恢复,这样做就是安全的。
如果我们使用redo日志机制,立即将数据元素备份到磁盘的需要就可以被避免。redo日志和undo日志的主要区别是:
1. undo日志在恢复时消除未完成事务的影响并忽略已提交事务,而redo日志忽略未完成的事务并重复已提交事务所做的改变。
2. undo日志要求我们在COMMIT日志记录达到磁盘前将修改后的数据元素写到磁盘,而redo日志要求COMMIT记录在任何修改后的值到达磁盘前出现在磁盘上
3. 当遵循undo规则U1和U2时,在恢复时我们需要的是发生改变的数据源的旧值,而是用redo日志恢复时,我们需要的是新值。
规则
在redo日志中,日志记录<T, v="" x,="">的含义是“事务T为数据库元素X写入的新值v”。在这个记录中没有指出X的旧值。每当一个事务T修改一个数据元素X时,必须网日志中写入一条形如<T, v="" x,="">的记录。
对于redo日志,数据和日志项达到磁盘的顺序可以用一条“redo规则”描述,这条规则成为先写日志规则:
R1: 在修改磁盘上的任何数据元素X以前,要保证与X的这一修改先骨干的所有的日志记录,包括更新记录<T, v="" x,="">及记录,都必须出现在磁盘上。
事务的COMMIT记录只有在事务完成后才能写入日志,因而提交记录必然在所有更新日志记录后,所以当使用redo日志时,与一个事务相关的材料写入到磁盘的顺序为:
1. 指出被修改元素的日志记录。
2. COMMIT日志记录
3. 改变数据元素自身
下面我们按照undo日志规则来考虑如下的事务T:
A := A*
B := B*
| 步骤 | 动作 | t | M-A | M-B | D-A | D-B | 日志 |
|------+-------------+----+-----+-----+-----+-----+------------|
| ) | | | | | | | <START T> |
| ) | READ(A, t) | | | | | | |
| ) | t := t* | | | | | | |
| ) | WRITE(A, t) | | | | | | <T, A, > |
| ) | READ(B, t) | | | | | | |
| ) | t := t* | | | | | | |
| ) | WRITE(B, t) | | | | | | <T, B, > |
| ) | | | | | | | <COMMIT T> |
| ) | FLUSH LOG | | | | | | |
| ) | OUTPUT(A) | | | | | | |
| ) | OUTPUT(B) | | | | | | |
恢复
redo规则R1的一个重要推论是,只要日志中没有记录,我们就知道事务T对数据库所做的更新都没有写到磁盘上。因此,恢复时对未完成事务的处理就可以像它们从未发生似的。然而,已提交的事务存在问题,因为我们不知道他们的那些数据库改变已经写到磁盘。幸运的是,redo日志正好有我们需要的信息:新值。我们可以讲新值写到磁盘而不管他们是否已经在磁盘上。在系统崩溃后要使用redo日志恢复,我们需要做以下事情:
1. 确定已提交的事务。
2. 从收不开始扫描日志。对遇到的每一个<T, v="" x,="">记录:
a) 如果T是未提交的事务,则什么也不做
b)如果t是提交的事务,则为数据库元素X写入值v
3. 对每个未完成的事务T,在日志中写入一个记录并刷新日志。
我们考虑上图中的日志,看看在不同步骤上发生故障时如何进行恢复。
1. 如果故障发生在第9步的任何时候,那么记录已被刷新到磁盘。T是一个提交的事务。当向前扫描日志时,日志记录<T, 16="" a,="">和<T, 16="" b,="">将A和B写入16.请注意,如果故障发生在第10和11步之间,那么写A是多余的,而写B还未发生,因而将B改变为16是恢复数据库的一致状态所必须的。如果故障发生在第11步以后,那么些A和写B都是多余的但也是无害的。
2. 如果故障发生在第8和第9步之间,那么尽管记录写入了日志,但可能还没有到达磁盘(依赖于日志是否因其他原因而刷新)。如果该记录到达磁盘,则恢复如情况1那样进行,而如果该记录没能到达磁盘,那么恢复和下面的情况3一样。
3. 如果故障发生在第8步以前,那么记录肯定没有达到磁盘。因此,T被看做一个未完成的事务。磁盘上的A和B不为T做任何改变,而最后一条记录被写到日志中。
检查点
对于redo日志的检查点,这儿有一个undo日志中没有的问题。由于已提交事务做的数据修改拷贝到磁盘的时间可能比事务提交的时间晚的多,因此我们不能仅仅考虑在我们决定创建检查点时活跃的事务。在检查点的开始和结束之间我们必须将已被提交事务修改的所有数据库元素写到磁盘。
另一方面,我们不需要等待活跃事务提交或中止就能完成检查点,因为他们呢无论如何都不被允许在那个时候将它们写到磁盘。进行redo日志的非静止检查点步骤如下:
1. 写入日志记录,其中T1,...,Tk是所有活跃(即未提交的)事务,并刷新日志
2. 将START CKPT记录写入日志时所有已提交事务已经写到缓冲区但还没有写到磁盘的数据写到磁盘
3. 写入日志记录并刷新日志
例:下图给出了一个可能的redo日志,其中发生了一个检查点。当我们开始检查点时,只有T2是活跃的,但T1所写的A值可能已经到达磁盘。如果没有,那么我们必须在检查点结束前将A拷贝回磁盘。我们表明检查点的技术在几个其他的事件后发生:T2为数据库元素C写入一个值,一个新事务T3开始并为D写入一个值。在检查点结束后发生的唯一的事情是T2和T3提交。
<START T1>
<T1, A, >
<START T2>
<COMMIT T1>
<T2, B, >
<START CKPT(T2)>
<T2, C, >
<START T3>
<T3, D, >
<END CKPT>
<COMMIT T2>
<COMMIT T3>
使用带检查点的redo日志恢复
首先假设崩溃发生前日志中的最后一条检查点记录是。现在,我们知道在对应的前提交的事务已经将其修改写到了磁盘,因此我们不必关心如何恢复这些事务的影响。但是Ti中的任一事务或检查点开始后启动的任一事务及时已经提交,都仍然可能未将其修改转到磁盘上。因此,需要进行恢复,但可以只关心最后一个START CKPT(T1,...,Tk)中提到的事务Ti与该日志记录中在日志中出现后开始的事务。在搜索日志时,我们在找到最早的记录后就不必继续向后看。蛋清注意,这些START记录可能出现在任意多个检查点前。将一个事务的所有日志记录向后链接在一起可以帮助我们找到所需记录。
现在建设日志中的最后一条检查点记录是:
<START CKPT(T1,...,Tk)>
我们不能确定再次检查点开始前提交的事务是否已经将其修改写到磁盘上。因此我们必须搜索到前一记录,找到与之匹配的记录,并重做这些已经提交的事务,这些事务要么在START CKPT后开始要么在Si中。
例:考虑上图中的日志。如果故障在尾部发生,我们向后搜索,找到记录。我们只需知道将所有在写记录后开始的事务以及出现在该记录的列表中的事务(T2)作为重做的候选者。因此,我们的候选集合是{T2, T3}。我们找到了记录和,于是我们知道他们都必须重做。我们向后搜索日志直到记录,为提交的事务找到更新记录<T2, b,="" 10="">, <T2, 15="" c,="">, <T3, 20="" d,="">。由于我们不知道这些改变是否已经到达磁盘,我们分别为B、C、D重新写入值10、15、20.
现在我们假设崩溃在记录和之间发生。恢复过程与上述过程类似,只不过T3不再是已提交的事务,因此其修改<T3, 20="" d,="">不能被重做,并且在恢复中不对D做任何改变,尽管日志记录处于被检查记录范围内。恢复后我们也要在日志中写入一条记录。
最后,假设崩溃正好在记录前发生。原则上,我们必须i型昂后搜索到倒数第二个START CKPT记录并得到其活跃事务里诶包。但是,这种情况下没有前一个检查点,因为我们必须一致走到日志的开头。因此我们确定已提交的只有T1,重做其动作<T1, a,="" 5="">,并且在恢复后将记录和写入到日志中。
Redo日志的更多相关文章
- dump redo日志文件的信息
通常会用到以下两个命令:1.'alter session'命令用来dump redo日志的文件头2.'alter system dump logfile'命令用来dump redo文件的内容 以上命令 ...
- Oracle redo 日志切换时间频率
DB: 11.2.0.3.0 查看Oracle的redo日志切换频率 两条SQL,原理是一样的,第二个用到了统计函数 时间单位:分钟 方法一. select * from v$log a where ...
- 检查REDO日志相关信息并生成HTML文件的脚本
生成HTML格式的文件 内容有: 检查数据库版本.REDO日志组情况, 最近20次日志切换频率检查--日志间的归档时间间隔, 这对查看数据库的IO繁忙时段 统计指定日期当天每小时的归档日志产生量--日 ...
- 关于数据库一致改关闭下redo日志文件丢失的处理办法的总结
数据库一致性关闭下redo日志文件丢失的处理办法(归档和非归档都行) 1. inactive log 在一致性关闭后删除重启时可以在mount下(不丢失数据) alter database clea ...
- 添加redo日志组和添加日志组多元化
查看redo日志组的状态和日志的位置. SQL> 没有被使用,所以切几次日志,组合4已生效. SQL> select * from v$log; GROUP# THREAD# SEQ ...
- 数据库中的undo日志、redo日志
MySQL中有六种日志文件,分别是:重做日志(redo log).回滚日志(undo log).二进制日志(binlog).错误日志(errorlog).慢查询日志(slow query log).一 ...
- 非IMU模式下DML语句产生的REDO日志内容格式解读
实验内容:非IMU模式下DML语句产生的REDO日志内容格式解读 最详细的解读是UPDATE的. 实验环境准备 11G中默认是开启IMU特性的,做此实验需要关闭此特性. alter system se ...
- Oracle11g温习-第七章:redo日志
2013年4月27日 星期六 10:33 1.redo (重做) log 的功能: 用于数据恢复 2.redo log 特征: [特征]: 1) 记录数据块的变化(DML.D ...
- 查看Oracle的redo日志切换频率
1.Oracle log 每次切换会记录到告警日志中 设想写个方案来查看log切换频率来判断Oracle log是否应该更改大小. 2.sql a.查看redo日志信息 select * from v ...
随机推荐
- socket学习笔记——线程(聊天程序)
server.c #include <stdio.h> #include <pthread.h> #include <semaphore.h> #include & ...
- SQL语句基础知识
1.关于SQL语句中exists与not exists的问题 course表如下:课程代号 课程名称 K01 奥运会主题曲 K02 喜爱的专辑 K03 VB技术大全 K04 经典歌曲 K05 个人单曲 ...
- 深入探讨ES6生成器
如果对于ES6生成器不熟悉,请先阅读并运行下http://www.cnblogs.com/linda586586/p/4282359.html里面的代码.当你感觉掌握了基础之后,我们可以深入探讨一些细 ...
- 怎么用一行代码解决CSS各种IE各种兼容问题
用一行代码来解决CSS在,IE6,IE7,IE8,IE9,IE10 中的各种兼容性问题. 在网站前端写代码的过程中,很多时间IE各个版本的兼容问题很难整.现在百度与谷歌都有了一行解决这种兼容性的代码了 ...
- Duilib扩展《01》— 双击、右键消息扩展
用过duilib的可能会发现,duilib中有些控件没能很好的区分左键.右键等消息.所以根据实际需要,我们需要进行相关区分处理,或者自行扩展. 一. 左键.右键消息区分 我们以CListUI控件来分析 ...
- WF4.0 自定义CodeActivity与Bookmark<第三篇>
一.自定义CodeActivity CodeActivity用于自定义一段代码,可实现你自己写的任意功能. 要注意的有两点: 1.自定义CodeActivity必须继承自CodeActivity; 2 ...
- Android IOS WebRTC 音视频开发总结(四一)-- QQ和webrtc打洞能力pk
很多人知道webrtc打洞能力很强,到底有多强但是不知道,比较好的方法就是跟QQ对比,但大多数公司很难模拟各种网络环境进行测试,比如联通,铁通,电信,移动,所以这次请小师妹在实验室下进行了一个比较全面 ...
- .NET Framework 中的字符编码
字符是可用多种不同方式表示的抽象实体. 字符编码是一种为受支持字符集中的每个字符进行配对的系统,配对时使用的是表示该字符的某些值. 例如,摩尔斯电码是一种为罗马字母表中的每个字符进行配对的字符编码,配 ...
- 使用Visual Studio Code开发Asp.Net Core WebApi学习笔记(九)-- 单元测试
本篇将结合这个系列的例子的基础上演示在Asp.Net Core里如何使用XUnit结合Moq进行单元测试,同时对整个项目进行集成测试. 第一部分.XUnit 修改 Project.json 文件内容, ...
- ios网络:应用一个请求的7个步骤
Splitting big tasks into small tasks is often one of the best ways to solve a problem. Thus, in the ...