我们知道,控制文件中记录了数据库中数据文件、日志文件的位置信息,检查点信息等重要信息,在数据库的Open阶段,Oracle根据控制文件中记录的这些信息找到这些文件,然后进行检查点及完整性检查。如果不存在问题就可以启动数据库,如果存在不一致或文件丢失则需要进行恢复。
Open阶段的一致性校验
在数据库Open的过程中,Oracle将会读取数据文件头块和控制文件信息,将两者进行对比,如果满足校验,则可以正常打开数据库;如果存在异常,则可能抛出相应异常信息,要求用户介入处理。
Oracle在Open阶段将要进行很多校验检查,其中主要的校验包括以下两项:
第一次检查数据文件头中的检查点计数(Checkpoint cnt)是否和控制文件中的检查点计数(Checkpoint cnt)一致。此步骤检查用以确认数据文件是来自同一版本,而不是从备份中恢复而来(因为Checkpoint Cnt不会被冻结,会一直被修改)。
可以通过一个简单的测试来说明一下Checkpoint Cnt(为了节省篇幅,省略了部分转储信息)的作用(以下实验测试信息来自Oracle 9iR2)。
首先通过如下命令在不同条件下转储控制文件,第一步转储正常状态下的控制文件:
SQL> alter session set events 'immediate trace name CONTROLF level 10';
Session altered.
将系统表空间置于热备份状态(热备状态会冻结表空间数据文件的检查点):
SQL> alter tablespace system begin backup;
Tablespace altered.
再来转储控制文件:
SQL> alter session set events 'immediate trace name CONTROLF level 10';
Session altered.
手工执行检查点并转储控制文件:
SQL> alter system checkpoint;
System altered.
SQL> alter session set events 'immediate trace name CONTROLF level 10';
Session altered.
结束表空间的热备状态,再次转储控制文件:
SQL> alter tablespace system end backup;
Tablespace altered.
SQL> alter session set events 'immediate trace name CONTROLF level 10';
Session altered.
注意:在Oracle 10g中,转储控制文件的事件有些变化,我们可以使用Level 8级转储获得控制文件信息:
alter session set events 'immediate trace name controlf level 8';
Oracle 10g中转储的内容包括如下部分,增强了Enabled Thread的位图信息,这部分信息是用来支持Oracle 10g网格并行计算的,以下信息来自单实例系统:
Database checkpoint: Thread=1 scn: 0x0000.0007276a
Threads: #Enabled=1, #Open=1, Head=1, Tail=1
enabled threads: 01000000 00000000 00000000 00000000 00000000 00000000
00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000
………
对于双实例RAC系统的信息显示如下:
Database checkpoint: Thread=2 scn: 0x0000.008a8531
Threads: #Enabled=2, #Open=2, Head=2, Tail=1
enabled threads: 01100000 00000000 00000000 00000000 00000000 00000000
00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000
…….
简要的来看一下前面测试过程中生成的跟踪文件信息(仅研究system表空间记录):
A)正常情况下转储控制文件
**********************************************************************
DATA FILE RECORDS
**********************************************************************
(blkno = 0x6, size = 180, max = 100, in-use = 24, last-recid= 574)
DATA FILE #1:
(name #4) /opt/oracle/oradata/hsjf/system01.dbf
creation size=32000 block size=8192 status=0xe head=4 tail=4 dup=1
tablespace 0, index=1 krfil=1 prev_file=0
unrecoverable scn: 0x0000.00000000 04/23/2004 01:20:52
Checkpoint cnt:1567 scn: 0x0000.0148181c 06/22/2004 18:58:46
Stop scn: 0xffff.ffffffff 06/22/2004 18:58:05
Creation Checkpointed at scn: 0x0000.000000ae 07/16/2003 03:40:10
注意这里记录的检查点计数器及SCN。
B)执行Begin backup以后的
注意到Checkpoint cnt增加了1,同时检查点SCN增加,对表空间执行Begin Backup会触发一次表空间检查点:
**********************************************************************
DATA FILE RECORDS
**********************************************************************
(blkno = 0x6, size = 180, max = 100, in-use = 24, last-recid= 574)
DATA FILE #1:
(name #4) /opt/oracle/oradata/hsjf/system01.dbf
creation size=32000 block size=8192 status=0xe head=4 tail=4 dup=1
tablespace 0, index=1 krfil=1 prev_file=0
unrecoverable scn: 0x0000.00000000 04/23/2004 01:20:52
Checkpoint cnt:1568 scn: 0x0000.01481939 06/22/2004 19:02:22
Stop scn: 0xffff.ffffffff 06/22/2004 18:58:05
Creation Checkpointed at scn: 0x0000.000000ae 07/16/2003 03:40:10
C)执行手工检查点
在表空间热备份模式下,手工执行检查点后,可以观察到,此时Checkpoint cnt增加,但是SCN不再改变。这是由于表空间处于热备份模式,数据文件检查点被冻结(热备模式下,数据库会生成额外的redo日志,在本书后面章节会有详细介绍):
**********************************************************************
DATA FILE RECORDS
**********************************************************************
(blkno = 0x6, size = 180, max = 100, in-use = 24, last-recid= 574)
DATA FILE #1:
(name #4) /opt/oracle/oradata/hsjf/system01.dbf
creation size=32000 block size=8192 status=0xe head=4 tail=4 dup=1
tablespace 0, index=1 krfil=1 prev_file=0
unrecoverable scn: 0x0000.00000000 04/23/2004 01:20:52
Checkpoint cnt:1569 scn: 0x0000.01481939 06/22/2004 19:02:22
Stop scn: 0xffff.ffffffff 06/22/2004 18:58:05
Creation Checkpointed at scn: 0x0000.000000ae 07/16/2003 03:40:10
D)End backup后的情况
此时数据文件头的冻结被取消,SCN开始变化
**********************************************************************
DATA FILE RECORDS
**********************************************************************
(blkno = 0x6, size = 180, max = 100, in-use = 24, last-recid= 574)
DATA FILE #1:
(name #4) /opt/oracle/oradata/hsjf/system01.dbf
creation size=32000 block size=8192 status=0xe head=4 tail=4 dup=1
tablespace 0, index=1 krfil=1 prev_file=0
unrecoverable scn: 0x0000.00000000 04/23/2004 01:20:52
Checkpoint cnt:1570 scn: 0x0000.01481941 06/22/2004 19:02:39
Stop scn: 0xffff.ffffffff 06/22/2004 18:58:05
Creation Checkpointed at scn: 0x0000.000000ae 07/16/2003 03:40:10
............
这就是检查点计数器及其在不同模式下的变化。
如果检查点计数检查通过,则数据库进行第二次检查。
第二次检查数据文件头的开始SCN和控制文件中记录的该文件的结束SCN是否一致,如果控制文件中记录的结束SCN等于数据文件头的开始SCN,则不需要对那个文件进行恢复(如果此前数据库异常崩溃,则结束SCN会保持在最大值(无穷大),数据库必须执行实例恢复以确保一致性)。
对每个数据文件都完成检查后,打开数据库,锁定数据文件,同时将每个数据文件的结束SCN设置为无穷大(稍后将详细解释这个过程)。
继续Mount阶段的测试,如果数据库中的某个文件丢失,在Mount数据库时早期版本的Oracle会在后台将文件丢失信息记录在告警日志文件中,但是并不会在前台给出提示;而在Open阶段,如果数据库无法锁定该文件,则会在前台发出错误警告,数据库将停止启动:
SQL> alter database open;
alter database open
*
ERROR at line 1:
ORA-01157: cannot identify/lock data file 3 - see DBWR trace file
ORA-01110: data file 3: '/opt/oracle/oradata/eygle/eygle01.dbf'
注意:仅在open阶段,Oracle才尝试打开并锁定数据文件,如果丢失或出现问题,则会给出错误提示。这时候就需要dba的介入进行处理,根据不同情况进行相应的恢复。
现在来看看告警日志文件中记录的Open过程中提示的错误信息.
Mon Sep 15 21:47:53 2008
alter database open
Mon Sep 15 21:47:53 2008
Errors in file /opt/oracle/admin/eygle/bdump/eygle_dbw0_17074.trc:
ORA-01157: cannot identify/lock data file 3 - see DBWR trace file
ORA-01110: data file 3: '/opt/oracle/oradata/eygle/eygle01.dbf'
ORA-27037: unable to obtain file status
Linux Error: 2: No such file or directory
Additional information: 3
Mon Sep 15 21:47:53 2008
ORA-1157 signalled during: alter database open...
在数据库出现问题的时候,提示中给出的可能是不完整的信息,而告警日志中则记录了完整的错误信息和错误号。所以当数据库出现故障时,应该优先检查alert_.log,从中发现关于故障的详细信息。
alert_.log通常称为告警日志文件,位置由参数background_dump_dest定义:
SQL> show parameter background_dump_dest
NAME TYPE VALUE
------------------------------------ ----------- ------------------------------
background_dump_dest string /opt/oracle/admin/eygle/bdump