回退段和重做日志缓冲区的区别和联系

 一直被回退段和重做日志缓冲区所困扰,现在总算有些明白,现在总结一下,其中的错误请大家指正。

从名字上看就可以看出回退段主要用于UNDO的,而重做日志缓冲区主要用于REDO的。

Oracle崩溃恢复步骤如下:

  首先rolling forward 前滚:由于oracle failure,sga中的内存信息丢失了,但是online redo log中还是存储了transaction信息,包括commited or uncommited data。可能这些修改信息并没有被oracle正确的来处理,包含两种情况:已经提交的还没有写入数据文件,或者没有提交的却被写入了数据文件。针对已 经提交的还没有写入数据文件就要发生前滚,在前滚过程中,smon会根据online redo log中的记录来完成对datafile的修改。保证已经提交的数据已经写入数据文件。

  接下来,前滚结束后,数据库正常open,此时用户可以正常连接,可以访问已经recover的commited data,但是对于那些属于unrecoverable transaction的uncommited data,会被oracle 加锁,是不可以访问的。  rolling back:假如有进程访问这些加锁的data,此时smon会对这些数据块做rollback回滚,从数据文件中撤销没有提交却被写入数据文件的数据。



回退段:把未提交事务的更改恢复到事务开始前的状态。

内部结构:

退段中的数据是以“回退条目”方式存储。
回退条目=块信息(在事务中发生改动的块的编号)+在事务提交前存储在块中的数据

在每一个回退段中oracle都为其维护一张“事务表”
在事务表中记录着与该回退段中所有回退条目相关的事务编号(事务SCN&回退条目)

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)存储(修改)到回滚段里的数据块时,就会产生变更向量。

3. 对于WORK03表内的数据块的变更向量
将修改后的值(9999)覆盖(修改)到WORK03表内的数据块时,就会产生变更向量。

由上面的例子可知,对于这个事务,重做记录理会有三个修改向量。当然可能有其他情况会产生重做记录, 例如修改的项目如果有索引,就必须修改索引,这时候就会产生第二个重做记录。 这时候的重做记录还是和第一个重做记录一样,包含不止一个变更向量。此外, 在事务之后运行commit语句,就会产生第三个重做记录。

那么,重做日志缓冲区中的内容何时才被写进重做日志文件中呢,当满足以下4个条件任一条时:
(1).Commit操作
(2).Redo buffer log 使用超过1/3
(3).Redo buffer log 使用超过 1 MB
(4).在DBWR开始写之前

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,写入到数据文件。

无论是写入缓冲区还是文件中,都是遵循先写入UNDO段、重做日志缓冲区,再写入数据高速缓冲区;先写入重做日志文件,再写入数据文件。

  当出现修改时,对数据库的所有修改(含所有段)首先写入重做日志缓冲区,当后面操作时数据丢失时可做重做操作。然后才是写入回退段,记录肯能要回退的修 改,若事务已经提交,则回退段的内部事务表会有标记,表示相应的回退条目不参与回退操作。然后才是写重做日志文件和数据文件。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值