回退段和重做日志缓冲区的区别和联系
一直被回退段和重做日志缓冲区所困扰,现在总算有些明白,现在总结一下,其中的错误请大家指正。
从名字上看就可以看出回退段主要用于UNDO的,而重做日志缓冲区主要用于REDO的。
Oracle崩溃恢复步骤如下:
首先rolling forward 前滚:由于oracle failure,sga中的内存信息丢失了,但是online redo log中还是存储了transaction信息,包括commited or uncommited data。可能这些修改信息并没有被oracle正确的来处理,包含两种情况:已经提交的还没有写入数据文件,或者没有提交的却被写入了数据文件。针对已经提交的还没有写入数据文件就要发生前滚,在前滚过程中,smon会根据online redo log中的记录来完成对datafile的修改。保证已经提交的数据已经写入数据文件。(SMON负责系统监视已经一些系统清理及恢复工作,这些工作主要包括:
从名字上看就可以看出回退段主要用于UNDO的,而重做日志缓冲区主要用于REDO的。
Oracle崩溃恢复步骤如下:
首先rolling forward 前滚:由于oracle failure,sga中的内存信息丢失了,但是online redo log中还是存储了transaction信息,包括commited or uncommited data。可能这些修改信息并没有被oracle正确的来处理,包含两种情况:已经提交的还没有写入数据文件,或者没有提交的却被写入了数据文件。针对已经提交的还没有写入数据文件就要发生前滚,在前滚过程中,smon会根据online redo log中的记录来完成对datafile的修改。保证已经提交的数据已经写入数据文件。(SMON负责系统监视已经一些系统清理及恢复工作,这些工作主要包括:
1.清理临时空间以及临时段
SMON负责在数据库启动时清理临时表空间中的临时段,或者一些异常操作过程遗留下来的临时段,例如,当创建索引过程中,创建期间分配给索引的Segment被标志为TEMPORARY,如果Create Index (或rebuild Index等)会话因某些原因异常中断,SMON负责清理这些临时段。
2.接合空闲空间
在DMT(字典管理表空间)中,SMON负责把那些在表空间中空闲的并且互相是邻近的Extent接合成一个较大的空闲扩展区,这需要表空间的pctincrease设置为非零值。
3.执行实例恢复(Instance recovery)
在实例恢复过程中,SMON的工作包括三个环节:应用Redo执行前滚、打开数据库提供访问、回滚未提交数据)
接下来,前滚结束后,数据库正常open,此时用户可以正常连接,可以访问已经recover
接下来,前滚结束后,数据库正常open,此时用户可以正常连接,可以访问已经recover
的commited data,但是对于那些属于unrecoverable transaction的uncommited data,会被oracle 加锁,是不可以访问的。 rolling back:假如有进程访问这些加锁的data,此时smon会对这些数据块做rollback回滚,从数据文件中撤销没有提交却被写入数据文件的数据。
回退段:把未提交事务的更改恢复到事务开始前的状态。
内部结构:
回退段中的数据是以“回退条目”方式存储。
回退条目=块信息(在事务中发生改动的块的编号)+在事务提交前存储在块中的数据
在每一个回退段中oracle都为其维护一张“事务表”
在事务表中记录着与该回退段中所有回退条目相关的事务编号(事务SCN&回退条目)
回退段:把未提交事务的更改恢复到事务开始前的状态。
内部结构:
回退段中的数据是以“回退条目”方式存储。
回退条目=块信息(在事务中发生改动的块的编号)+在事务提交前存储在块中的数据
在每一个回退段中oracle都为其维护一张“事务表”
在事务表中记录着与该回退段中所有回退条目相关的事务编号(事务SCN&回退条目)
undo的原因:
在oracle正常运行时,为了提高效率,加入用户还没有commit,但是空闲内存不多或设置了CHECKPOINT时,会由DBWR进程将脏数据块写入到数据文件中,以便腾出宝贵的内存供其它进程使用。这就是需要UNDO的原因。因为还没有发出commit语句,但是oracle的dbwr进程已经将没有提交的数据写到数据文件中去了,此时数据文件中存放commit和uncommit的数据。也就是说即使数据已经写入了数据文件,仍然能回滚,只要回滚段的内部事务表标记为active(事务未提交),若标记为inactive(事务已提交)就不能回滚了。
事务分配策略:
oracle基于两个原则给事务分配回滚段。首先oracle试图将一个新的事务指派给某个拥有最少活动事务数的回滚段;如果没有单个段能满足这个需求,那么该事务将被指派给某个段来保存undo信息,以便此undo信息能够尽可能长的时间内被用于读一致性视图保留。
在oracle正常运行时,为了提高效率,加入用户还没有commit,但是空闲内存不多或设置了CHECKPOINT时,会由DBWR进程将脏数据块写入到数据文件中,以便腾出宝贵的内存供其它进程使用。这就是需要UNDO的原因。因为还没有发出commit语句,但是oracle的dbwr进程已经将没有提交的数据写到数据文件中去了,此时数据文件中存放commit和uncommit的数据。也就是说即使数据已经写入了数据文件,仍然能回滚,只要回滚段的内部事务表标记为active(事务未提交),若标记为inactive(事务已提交)就不能回滚了。
事务分配策略:
oracle基于两个原则给事务分配回滚段。首先oracle试图将一个新的事务指派给某个拥有最少活动事务数的回滚段;如果没有单个段能满足这个需求,那么该事务将被指派给某个段来保存undo信息,以便此undo信息能够尽可能长的时间内被用于读一致性视图保留。
事务可以用以下语句申请指定的回滚段:
SET TRANSTRACTION USE ROLLBACK SEGMENT rollback_segment
事务将以顺序,循环的方式使用回滚段的区(EXTENTS),当前区用满后移到下一个区。几个事务可以写在回滚段的同一个区,但每个回滚段的块只能包含一个事务的信息。
回滚段的扩张(EXTEND):
当前回滚段区的所有块用完而事务还需要更多的回滚空间时,回滚段的指针将移到下一个区。当最后一个区用完,指针将移到第一个区的前面。回滚段指针移到下一个区的前提是下一个区没有活动的事务,同时指针不能跨区。当下一个区正在使用时,事务将为回滚段分配一个新的区,这种分配称为回滚段的扩展。回滚段将一直扩展到该回滚段区的个数到达回滚段的参数MAXEXTENTS的值时为止。
重做日志缓冲区:把已提交事务的更改写到数据文件
内部结构:
数据库的更改的最小记录单位是变更向量,一连串的变更向量集合起来称为重做记录 (REDO Record)。每个变更向量中记录了事务对数据库中某个块所做的修改。包括修改对象、前值、后值、该修改操作的事务号和该事务是否已提交等信息。有些事务(transaction)会产生不止一个重做记录。
redo的原因:
每次commit时,将数据的修改立即写到online redo中,但是并不一定同时将该数据的修改写到数据文件中。因为该数据已经提交,但是只存在联机日志文件中,所以在恢复时需要将数据从联机日志文件中出来,重新应用一下,使已经更改数据在数据文件中也改过来!
发生时刻:
对于数据库内所有被更改的数据块(segment),Oracle会把所有更改内容清楚记录在REDO日志缓冲中。 所谓所有更改内容,当然包括数据段,还有索引段和回滚段(rollback segment)。 数据库内任意数据块所发生的一个更改,会被写成一个变更向量(Change Vector)。
例子:
──SQL语句──
*************************************************************
UPDATE WORK03
SET EMPNO = 9999
WHERE EMPNO = 1111 ;
※ EMPNO项目尚未创建索引
*************************************************************
运行上面的UPDATE语句之后,会产生下面的变更向量。
提交更改是内存条吗1. 对于回滚段的事务表(标题)的变更向量
当含有修改的数据块的地址、该事务的状态(commit或active)、 以及存有该事务的UNDO的回滚段的位置的事务表被修改的时候,就会产生变更向量。
2. 对于回滚段的数据块的变更向量
将修改前的值(1111)存储(修改)到回滚段里的数据块时,就会产生变更向量。
WHERE EMPNO = 1111 ;
※ EMPNO项目尚未创建索引
*************************************************************
运行上面的UPDATE语句之后,会产生下面的变更向量。
提交更改是内存条吗1. 对于回滚段的事务表(标题)的变更向量
当含有修改的数据块的地址、该事务的状态(commit或active)、 以及存有该事务的UNDO的回滚段的位置的事务表被修改的时候,就会产生变更向量。
2. 对于回滚段的数据块的变更向量
将修改前的值(1111)存储(修改)到回滚段里的数据块时,就会产生变更向量。
3. 对于WORK03表内的数据块的变更向量
将修改后的值(9999)覆盖(修改)到WORK03表内的数据块时,就会产生变更向量。
由上面的例子可知,对于这个事务,重做记录理会有三个修改向量。当然可能有其他情况会产生重做记录, 例如修改的项目如果有索引,就必须修改索引,这时候就会产生第二个重做记录。 这时候的重做记录还是和第一个重做记录一样,包含不止一个变更向量。此外, 在事务之后运行commit语句,就会产生第三个重做记录。
那么,重做日志缓冲区中的内容何时才被写进重做日志文件中呢,当满足以下4个条件任一条时:
(1).Commit操作
(2).Redo buffer log 使用超过1/3
(3).Redo buffer log 使用超过 1 MB
(4).在DBWR开始写之前(当DBWn启动,而且发现要写的脏数据还没有写入redo file的时
候,也会先启动LGWR,等待写入Redo file才即系执行的。)
LGWR写进程就会被触发,从而把重做日志缓冲区中的内容写进重做日志文件。
COMMIT时两者的动作(纯属个人理解):
下面看一下,当执行"UPDATE emp SET sal=2000 WHERE empno=7788;"这条语句时的过程:
1. Oracle将emp表中empno=7788的记录的sal的值的变化记录到重做日志缓冲区中(也把UNDO段的变更记录到重做日志缓冲区中)
2. 将旧值1000记录到UNDO段所对应的缓冲区中;
3. 在为该事务指定的回退段中的内部事务表内记录下这个事务已经被提交,并且生成一个
LGWR写进程就会被触发,从而把重做日志缓冲区中的内容写进重做日志文件。
COMMIT时两者的动作(纯属个人理解):
下面看一下,当执行"UPDATE emp SET sal=2000 WHERE empno=7788;"这条语句时的过程:
1. Oracle将emp表中empno=7788的记录的sal的值的变化记录到重做日志缓冲区中(也把UNDO段的变更记录到重做日志缓冲区中)
2. 将旧值1000记录到UNDO段所对应的缓冲区中;
3. 在为该事务指定的回退段中的内部事务表内记录下这个事务已经被提交,并且生成一个
惟一的SCN记录在内部事务表中,用于惟一标识这个事务;(表明事务已提交的数据无法undo,只能作redo操作)
4.将新值2000存放到EMP段所对应的数据高速缓冲区中;
5.将重做日志缓冲区的内容写入重做日志文件;
6.Oracle服务进程释放事务所使用的所有记录锁与表锁;
7.Oracle通知用户事务提交完成;(只有把重做日志缓冲区的重做记录成功写入重做日志文件中后,才被认为事务成功提交)
8.Oracle将该事务标记为已完成;
9.Commit,写入到数据文件。
4.将新值2000存放到EMP段所对应的数据高速缓冲区中;
5.将重做日志缓冲区的内容写入重做日志文件;
6.Oracle服务进程释放事务所使用的所有记录锁与表锁;
7.Oracle通知用户事务提交完成;(只有把重做日志缓冲区的重做记录成功写入重做日志文件中后,才被认为事务成功提交)
8.Oracle将该事务标记为已完成;
9.Commit,写入到数据文件。
无论是写入缓冲区还是文件中,都是遵循先写入UNDO段、重做日志缓冲区,再写入数据高速缓冲区;先写入重做日志文件,再写入数据文件。(应该是:重做日志缓冲区、UNDO段)
当出现修改时,对数据库的所有修改(含所有段)首先写入重做日志缓冲区,当后面操作时数据丢失时可做重做操作。然后才是写入回退段,记录可能要回退的修改,若事务已经提交,则回退段的内部事务表会有标记,表示相应的回退条目不参与回退操作。然后才是写重做日志文件和数据文件。
不明白处:
当出现修改时,对数据库的所有修改(含所有段)首先写入重做日志缓冲区,当后面操作时数据丢失时可做重做操作。然后才是写入回退段,记录可能要回退的修改,若事务已经提交,则回退段的内部事务表会有标记,表示相应的回退条目不参与回退操作。然后才是写重做日志文件和数据文件。
不明白处:
1、当变更向量写入重做日志缓冲区后,数据库出现问题倒是内存数据消失,那就来不及写入重做日志文件了,那如何才能恢复数据呢。还有能否根据重做日志缓冲区的记录来redo?(答:重做日期缓冲区也是属于内存的,当系统发生故障的时候里面的部分内容应该也是会丢失的,也就是说这部分数据时没办法恢复的。不过LGWR这个进程会频繁的将LOG BUFFER里的内容写入LOG FILE,所以说即便发生你说的这种情况,那么丢失的数
据量也是很少的。
注意到红字体标出来的部分内容,因为有些在重做日期缓冲区内的内容是已经写到LOG FILE里了,比如说已经COMMIT了的那部分。触发LGWR把日志内容从LOG BUFFER写到LOG FILE的条件有很多,LGWR进程将日志缓冲区的日志信息写入联机日志文件,触发的5个条件:
注意到红字体标出来的部分内容,因为有些在重做日期缓冲区内的内容是已经写到LOG FILE里了,比如说已经COMMIT了的那部分。触发LGWR把日志内容从LOG BUFFER写到LOG FILE的条件有很多,LGWR进程将日志缓冲区的日志信息写入联机日志文件,触发的5个条件:
一,前台进程触发
1.用户发出commit,rollback语句。
2.日志缓冲区不到足够的内存来放日志信息。
二,每隔3秒钟
三,日志信息的数量达到日志缓冲区的1/3.
四,日志信息数量达到1MB
五,DBWn启动时,如果发现有脏数据块对应的重做条目还没写到联机日志文件,则触发L
GWR,并等LGWR写完,DBWn才继续。
回复:只有把重做日志缓冲区的重做记录成功写入重做日志文件中后,才被认为事务成功提交,若出现1的问题,那么事务就是提交失败,所以不存在REDO问题。并且写入重做日志文件的记录含COMMIT和UNCOMMIT的,没有插入提交记录的事务相关重做记录是不会引起redo操作的)
2、既然重做日志缓冲区已经记录了所有的修改记录,那么为什么不直接用它就好了,还要用回滚段呢?(回滚段记录的是修改的数据的前镜像,而重做日志缓冲区记录的就是你当前的操作。
举个例子,可能会形象点
SQL> select * from t2;
ID
----------
1
举个例子,可能会形象点
SQL> select * from t2;
ID
----------
1
这个时候你执行一条更新语句
update t1 set id=3;
这个时候重做日志缓冲区里存的就是你这条UPDATE语句,如果你想回滚的话,你怎么回滚?你不知道这个ID以前的值是1呀,你只能知道修改后的值是3而已。
而回滚段里就存有数据的前镜像,也就是id=1这个值。)
update t1 set id=3;
这个时候重做日志缓冲区里存的就是你这条UPDATE语句,如果你想回滚的话,你怎么回滚?你不知道这个ID以前的值是1呀,你只能知道修改后的值是3而已。
而回滚段里就存有数据的前镜像,也就是id=1这个值。)
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。
发表评论