Chinaunix首页 | 论坛 | 博客
  • 博客访问: 92755
  • 博文数量: 46
  • 博客积分: 1400
  • 博客等级: 上尉
  • 技术积分: 470
  • 用 户 组: 普通用户
  • 注册时间: 2006-12-15 03:05
文章分类

全部博文(46)

文章存档

2011年(1)

2008年(45)

我的朋友

分类: Oracle

2008-03-13 21:23:35

数据库恢复的内在机制

数据库在事务当中发生变化,Oraccle 数据库系统使用系统变更号(System Change Number,简写为SCN)来记录数据库内部的变化。数据库内部的很多事件,以及用户通过SQL 语句对数据库内容进行变化,会让SCN 值增长。

  我们知道,当应用程序提交(Commit)某个事务时,先是日志写入进程(LGWR)将Log Buffer 中的该事务的纪录写入到联机重做日志文件成功后,才由Service Process 通知相关的用户进程:你的提交已成功。


检查点出现,将推动检查点时刻前的日志文件中所参考的数据块的修改,已经被DBWR 写入到数据文件中。CKPT进程会纪录该检查点的Checkpoint SCN 的信息到数据文件和控制文件中。从而推动了数据库的一个同步点如果在下一个同步点完成之前,数据库发生失败,在数据库的实例恢复从系统当前检查点开始,运用后面的日志进行实例恢复。

可以看出,检查点的出现,可以让数据库在运行时,定期的维护日志文件,数据文件进行状态一致性。有些类似于我们生活中:不同的公司定期的账目结清,当一个检查点完成后,大家都承认,这个时间之前的一切账目已经结清。

 

一、Oracle 是如何确定需要恢复的

1、正常运行的数据库的有关检查点信息纪录

在数据库正常OPEN 运行时,当一个检查点完成后,Oracle存储新的System Checkpoint SCN

到控制文件中,我们可以通过下面的查询来得到该值。

SQL> select a.CHECKPOINT_CHANGE# from v$database a;

CHECKPOINT_CHANGE#

------------------

2798752785243

SQL> select a.NAME,a.CHECKPOINT_CHANGE# from v$datafile a;

NAME CHECKPOINT_CHANGE#

-------------------------------------------------------------------- ------------------

C:ORACLEORADATAJACKYSYSTEM01.DBF 2798752785243

C:ORACLEORADATAJACKYUNDOTBS01.DBF 2798752785243

C:ORACLEORADATAJACKYCWMLITE01.DBF 2798752785243

C:ORACLEORADATAJACKYDRSYS01.DBF 2798752785243

C:ORACLEORADATAJACKYEXAMPLE01.DBF 2798752785243

C:ORACLEORADATAJACKYINDX01.DBF 2798752785243

C:ORACLEORADATAJACKYODM01 2798752785243

C:ORACLEORADATAJACKYTOOLS01.DBF 2798752785243

D:DATAFILEUSERS01.DBF 2798752785243

C:ORACLEORADATAJACKYXDB01.DBF 2798752785243

C:ORACLEORADATAJACKYBLOCK.DBF 2798752785243

C:ORACLEORADATAJACKYRMAN.DBF 2798752785243

C:ORACLEORADATAJACKYTEST01.DBF 2798752785243

13 rows selected

Oracle 也会在每个数据文件的头部存储存储Checkpoint SCN的值,名称叫做Start SCN。主要作用是在数据库Open的时候,用于和控制文件有关信息进行比较,从而确定是否需要做恢复。

SQL> select a.NAME,a.CHECKPOINT_CHANGE# from v$datafile_header a;

NAME CHECKPOINT_CHANGE#

-------------------------------------------------------------------- ------------------

C:ORACLEORADATAJACKYSYSTEM01.DBF 2798752785243

C:ORACLEORADATAJACKYUNDOTBS01.DBF 2798752785243

C:ORACLEORADATAJACKYCWMLITE01.DBF 2798752785243

C:ORACLEORADATAJACKYDRSYS01.DBF 2798752785243

C:ORACLEORADATAJACKYEXAMPLE01.DBF 2798752785243

C:ORACLEORADATAJACKYINDX01.DBF 2798752785243

C:ORACLEORADATAJACKYODM01 2798752785243

C:ORACLEORADATAJACKYTOOLS01.DBF 2798752785243

D:DATAFILEUSERS01.DBF 2798752785243

C:ORACLEORADATAJACKYXDB01.DBF 2798752785243

C:ORACLEORADATAJACKYBLOCK.DBF 2798752785243

C:ORACLEORADATAJACKYRMAN.DBF 2798752785243

C:ORACLEORADATAJACKYTEST01.DBF 2798752785243

13 rows selected

Oracle 在控制文件为每个数据文件存储Stop SCN 的值,在正常OPEN 的数据库中,该值为一个无穷大,查询时,显示NULL

SQL> select a.NAME,a.LAST_CHANGE# from v$datafile a;

NAME LAST_CHANGE#

-------------------------------------------------------------------------------- ------------

C:ORACLEORADATAJACKYSYSTEM01.DBF

C:ORACLEORADATAJACKYUNDOTBS01.DBF

C:ORACLEORADATAJACKYCWMLITE01.DBF

C:ORACLEORADATAJACKYDRSYS01.DBF

C:ORACLEORADATAJACKYEXAMPLE01.DBF

C:ORACLEORADATAJACKYINDX01.DBF

C:ORACLEORADATAJACKYODM01.DBF

C:ORACLEORADATAJACKYTOOLS01.DBF

D:DATAFILEUSERS01.DBF

C:ORACLEORADATAJACKYXDB01.DBF

C:ORACLEORADATAJACKYBLOCK.DBF

C:ORACLEORADATAJACKYRMAN.DBF

C:ORACLEORADATAJACKYTEST01.DBF

13 rows selected

2、正常关闭的数据库的有关检查点记录信息

当我们正常关闭数据库(Shutdown immediate 或者Shutdown normal),此时会执行一个检查点的过程,该过程会把控制文件中记录的每个数据文件的Stop SCN 进行设置,等于每个数据文件头部的StartSCN。所以,我们以start mount 加载数据库,然后进行上面的查询。得到下图的结果:

正常关闭数据库,在Mount 模式下启动数据库,查询System Checkpoint SCN Data File

Checkpoint SCN 以及Start SCNStop SCN 变得一致。

SQL> startup mount;

ORACLE 例程已经启动。

Total System Global Area 135338868 bytes

Fixed Size 453492 bytes

Variable Size 109051904 bytes

Database Buffers 25165824 bytes

Redo Buffers 667648 bytes

数据库装载完毕。

SQL> select checkpoint_change# from v$database;

CHECKPOINT_CHANGE#

------------------

2.7988E+12

SQL> select name,checkpoint_change#,last_change# from v$datafile where name like '%USER%';

NAME CHECKPOINT_CHANGE# LAST_CHANGE#

-------------------------------

D:DATAFILEUSERS01.DBF 2.7988E+12 2.7988E+12

SQL>

OPEN 数据库时,Oracle 先检查数据文件头部所记录的Start SCN 和控制文件中所记录的数据文件的Checkpoint SCN 是否一致,如果一致,Oracle 进一步检查Start SCN 和控制文件中记录的数据文件的Stop SCN,如果一致。这表示所有的已经被修改的数据块已经反映到了数据文件中。在是正常关闭数据库的情况。数据库可以正常OPEN,无需作实例恢复,当数据库打开后,控制文件中的Stop SCN 会变为NULL

SQL> alter database open;

数据库已更改。

SQL> select name,checkpoint_change#,last_change# from v$datafile where name like '%USER%';

NAME CHECKPOINT_CHANGE# HANGE#

--------------------------------------------------------------------------------

D:DATAFILEUSERS01.DBF 2.7988E+12

数据库在打开时,对每个数据文件要进行两个比对:

  A、控制文件中记录的数据文件的Checkpoint SCN  和 数据文件头部所记录的Start SCN 是否相等;

  B、然后检查:控制文件中记录数据文件的Stop SCN 和 数据文件头部所记录的Start SCN 是否相等;

3、实例Crash 后的有关检查点记录信息

SQL> create table test (a number) tablespace test ;

Table created

SQL> insert into test values(1);

1 row inserted

SQL> shutdown abort

ORACLE 例程已经关闭。

SQL> startup mount

ORACLE 例程已经启动。

Total System Global Area 135338868 bytes

Fixed Size 453492 bytes

Variable Size 109051904 bytes

Database Buffers 25165824 bytes

Redo Buffers 667648 bytes

数据库装载完毕。

SQL> select checkpoint_change# from v$database;

CHECKPOINT_CHANGE#

------------------

2.7988E+12

SQL> select name,checkpoint_change#,last_change# from v$datafile where name like '%TEST%';

NAME CHECKPOINT_CHANGE# LAST_CHANGE#

------------------ ------------

C:ORACLEORADATAJACKYTEST01.DBF 2.7988E+12 NULL

SQL> select name,checkpoint_change# from v$datafile_header where name like'%TEST%';

NAME CHECKPOINT_CHANGE#

------------------

C:ORACLEORADATAJACKYTEST01.DBF 2.7988E+12

从上面可以看出控制文件中记录的Stop SCN (查询中的Last_Change#)为无穷大。不等于数据文件头部的Start SCN这表示:数据库在Crash 关闭时,没有进行Checkpoint和相关过程。实例在Open 之前,需要做实例恢复。

实例恢复由Oracle 实例自动完成。Oracle 依照控制文件记录的数据库的Checkpoint SCN 定位联机重做日志文件中的重做日志位置。从该位置开始应用重做日志一直到Crash 时日志结束点。这中间所有被提交的事务,将会确保写入到数据文件,这个过程叫做前滚过程(Roll Forward)。没有提交的活动事务将从回滚段中恢复过来;在上面的例子中Crash 前,我们插入了一行数据,但是没有被提交。所以,实例恢复后,将查询不到该行数据。

SQL> alter database open;oracle 实例自动完成)

数据库已更改。

SQL> select * from test;

未选定行

控制文件中记录的数据文件的Checkpoint SCN 和数据文件头部所记录的Start SCN 始终是相等的。这是因为数据库在经历检查点后,检查点后台进程会同时修改数据库的System Checkpoint SCN、控制文件中记录的数据文件的Checkpoint SCN、以及数据文件头文件中的Start SCN,设置它们的值为检查点开始的系统变更号SCN

只有在当数据文件丢失时,我们使用以前的备份的数据文件时,这个比对就不一致,数据文件头部纪录的Start SCN 将会小于控制文件中所记录的该数据文件的Checkpoint SCN。将使用到必要的归档/联机日志文件进行恢复。

4、使用备份的控制文件进行恢复

   在正常情况下,数据文件头部所记录的Start SCN 都不会大于控制文件中记录的数据文件的CheckpointSCN 的。我们也许觉得奇怪,控制文件已经记录了Checkpoint SCN,为何还需要纪录System Checkpoint SCN 呢,这主要有下列原因:

A、有时候,数据库的某些表处于只读模式,当系统经历检查点,只读表空间的数据文件头部的StartSCN 将不会更新; System Checkpoint SCN 有助于识别这一点。

B有时候,我们的控制文件丢失了,当我们使用以前备份的控制文件。此时,数据文件头部的Start SCN会大于控制文件的System Checkpoint SCN,这表明使用了备份的控制文件。如果我们使用正常的recover database 的恢复方法,将会出现错误消息。我们应该使用:recover database using backup controlfile;

二、实例恢复的详细过程

当我们系统掉电,或者通过Shutdown abort 关闭数据后,再重新打开数据库前,系统会自动进行恢复,这个恢复过程可以分为下列三个阶段

A.     前滚过程,前滚是按照redo file的记录来前滚的,不管有没有commit都会利用联机日志文件的有关重做信息,写入到数据文件中。

前滚是按照redo file的记录来前滚的,不管有没有commit,只要有已经写入redo就会前滚,所以前滚完成后,data file中可能会有 没有提交的数据,这样才需要后面的回退过程。另外,由于undo的生成也是要记录redo的,所以这个过程还会按照redo重新生成后面回退时需要的undo信息。另外,实例恢复是在从最近的一次checkpoint后开始到失败的一刻,所以,增加checpoint的频率可以减少实例恢复所需要的时间,但同时会影响系统的性能,所以需要在这两者之间做一个权衡。

前滚又叫缓冲区恢复cache recovery,顾名思义,就是恢复已经在内存中存在但还没有写入数据文件中的内容,而不管这个内容所在的事务是不是已经提交。

B.      数据库打开:进行完毕前滚过程后,数据库就可以打开,可以接受用户连接访问了

C.         回退(Roll Back) 过程:没有提交的事务将会被回退。
回退阶段又叫事务恢复transaction recoery,也就是恢复完后将保持事务一致性。该过程保证数据库中的数据只有已经提交的,没有提交的事务将会被回退。

1redo buffer 的操作

当用户User A 发出数据修改命令: UPDATE emp SET sal=10 WHERE id=1234

数据块被读入DB Buffer 中;相应的回滚段的数据块也被读入到DB Buffer 中,并将数修改前的值信息记录下来,作为前映像; 这样的变化过程会作为REDO 实体记录在Redo Buffer中。

然后,修改DB Buffer 中数据块的值为新值;并在Redo Buffer中生成重做信息。在Redo Buffer 中的重做记录实体主要包含三部分信息:

 事务的识别号

 修改目标Column 的地址

 修改Column 的新值

然后,用户User A 发出提交命令:

Commit

Redo Buffer 中生成相应的重做信息实体,该信息主要包含三部分:

A、一个指示该实体是一个Commit。如果是Rollback 或者是Checkpoint也有相应的标志。

B、时间。

C、当前的SCN 号。

SCN System Change Number,用来帮助识别数据库的事务,数据库在事务当中变化,我们可以认为SCN 是数据库变化的时钟SCN 一般用来标识数据库内事务的开始,事务的提交,回滚,或者是检查点的时间,以及其他数据库内部的事件。

LGWR 进程负责将Log Buffer 中内容写入到联机日志文件中去。触发LGWR 工作的机制有:

  用户提交

  Redo Buffer 1/3 写满了

  Redo Buffer 中写满1M 内容

超时3

DBWR

总之,LGWR是一个极为频繁的工作进程,从而保证事务信息被非常快速,及时地写入到联机日志文件。

当联机日志文件Log 1 写满之后,则发生日志切换到Log 2。在正常的生产数据库上,联机日志文件的组数和大小需要灵活考虑,通常情况下,较好的经验值是让日志切换的发生时间间隙为20-30分钟之间。这只是一个建议,某些情况或者某些特别的需求,也有要求日志切换更加频繁或者间隙更长。

2、数据库恢复的过程

因为系统掉电或者不正常关闭数据库(Shutdown abort),当数据库要重新打开前,系统自动会进行恢复过程。这个恢复过程是首先从读取控制文件的信息开始的。控制文件中记录的Checkpoint RBA (Redo Byte Address) 指向联机日志文件中一个恢复开始点。由于每次操作都在redo log都有记录,所以可以从这个开始点往后的重做信息直到重做信息的结束点,每次操作都进行重演,也就是恢复。

对于已经提交的事务,事务被重新提交(Re-Commit),这就是前滚的概念。然而,在数据库Crash 前没有提交的事务,当时所引起的数据文件的修改变化。在恢复过程后,数据库打开运行期间,如果有用户访问到这些数据块,才利用以前的前映像来重新修改回去。这是未提交的事务的回退过程。

oracle9i开始,Oracle 改善了恢复过程中前滚的操作。这个小的改变提高了实例恢复过程中的效率--在实例失败后可以更快速的恢复过来。当一次DBWR 完成后,LGWR会在Redo Buffer 中记录该次写完成的数据块。

这种新的快速前滚机制分为两个步骤:

A 先快速选择哪些块的事务需要处理;扫描一次Redo Log, 根据DBWR的写块记录滤去已经写入了数据文件的那些重做实体的处理,这个过程不需要读取数据文件块。速度非常快。

B 然后对选择的块进行处理;

这个小的改善,显剧减少了恢复过程中去读取和修改数据块的数量。再加上Checkpoint 的同步特性和有关参数控制。让实例Crash后的快速恢复过程的时间是快速的,可控的。

阅读(1018) | 评论(1) | 转发(0) |
给主人留下些什么吧!~~

chinaunix网友2008-09-05 10:29:14

学的非常的透彻! 好!好!