zoukankan      html  css  js  c++  java
  • DBA入门之Oracle数据库的启动

    1. 数据库的启动

    首先来分析一下数据库的启动过程,Oracle数据库的启动主要包含3个步骤;

    (1)启动数据库到nomount状态;

    (2)启动数据库到mount状态;

    (3)启动数据库到open状态。

    下面逐个来看看各个步骤的具体过程与其含义。

    1.1. 启动数据库到nomount状态

    在启动的第一步骤,Oracle首先寻找参数文件(pfile/spfile),然后根据参数文件中的设置,创建实例,分配内存,启动后台进程。在这里可以看到,只有拥有了一个参数文件,就可以凭之启动实例(Instance),这一步骤并不需要任何控制文件或数据文件的参与。在创建数据库时,如果在这一步骤出现问题,那么通常可能是系统配置(内核参数等)存在问题,用户需要检查是否分配了足够的系统资源等;

    来看一下启动到nomount状态的过程:

    [oracle@czjie ~]$ cd $ORACLE_HOME/dbs

    [oracle@czjie dbs]$ ls

    hc_ORCL.dat init.ora lkORCL spfileORCL.ora spfileORCL.ora.bak0

    initdw.ora initORCL.ora orapwORCL spfileORCL.ora.bak [oracle@czjie dbs]$ sqlplus "/ as sysdba"

    SQL*Plus: Release 10.2.0.4.0 - Production on Fri Nov 11 22:19:24 2011

    Copyright (c) 1982, 2007, Oracle. All Rights Reserved.

    Connected to an idle instance.

    SQL> startup nomount

    ORACLE instance started.

    Total System Global Area 218103808 bytes

    Fixed Size 1266680 bytes

    Variable Size 121637896 bytes

    Database Buffers 92274688 bytes

    Redo Buffers 2924544 bytes

    注意:Oracle根据参数文件的内容,创建了instance,分配了相应的内存区域,启动了相应的后台进程。

    此时观察警报日志文件(alert_<sid>.log),可以看到这一阶段的启动过程,读取参数文件,应用参数启动实例,所有在参数文件中定义的非缺省参数都会记录在警报日志文件中:

    Fri Nov 11 22:20:49 2011

    Starting ORACLE instance (normal)

    LICENSE_MAX_SESSION = 0

    LICENSE_SESSIONS_WARNING = 0

    Picked latch-free SCN scheme 2

    Using LOG_ARCHIVE_DEST_10 parameter default value as USE_DB_RECOVERY_FILE_DEST

    Autotune of undo retention is turned on.

    IMODE=BR

    ILAT =18

    LICENSE_MAX_USERS = 0

    SYS auditing is disabled

    ksdpec: called for event 13740 prior to event group initialization

    Starting up ORACLE RDBMS Version: 10.2.0.4.0.

    System parameters with non-default values:

    processes = 150

    __shared_pool_size = 104857600

    __large_pool_size = 4194304

    __java_pool_size = 12582912

    __streams_pool_size = 0

    nls_length_semantics = BYTE

    resource_manager_plan =

    sga_target = 218103808

    control_files = /opt/ora10g/oradata/ORCL/control01.ctl, /opt/ora10g/oradata/ORCL/control02.ctl, /opt/ora10g/oradata/ORCL/control03.ctl

    db_block_size = 8192

    __db_cache_size = 92274688

    compatible = 10.2.0.1.0

    db_file_multiblock_read_count= 16

    db_recovery_file_dest = /opt/ora10g/flash_recovery_area

    db_recovery_file_dest_size= 2147483648

    undo_management = AUTO

    undo_tablespace = UNDOTBS1

    undo_retention = 900

    remote_login_passwordfile= EXCLUSIVE

    db_domain = 192.168.1.106

    dispatchers = (PROTOCOL=TCP) (SERVICE=ORCLXDB)

    job_queue_processes = 10

    background_dump_dest = /opt/ora10g/admin/ORCL/bdump

    user_dump_dest = /opt/ora10g/admin/ORCL/udump

    core_dump_dest = /opt/ora10g/admin/ORCL/cdump

    audit_file_dest = /opt/ora10g/admin/ORCL/adump

    db_name = ORCL

    open_cursors = 300

    pga_aggregate_target = 71303168

    aq_tm_processes = 0

    然后后台进程一次启动

    PSP0 started with pid=3, OS id=2789

    PMON started with pid=2, OS id=2787

    MMAN started with pid=4, OS id=2791

    DBW0 started with pid=5, OS id=2793

    LGWR started with pid=6, OS id=2795

    SMON started with pid=8, OS id=2799

    CKPT started with pid=7, OS id=2797

    RECO started with pid=9, OS id=2801

    MMON started with pid=11, OS id=2805

    CJQ0 started with pid=10, OS id=2803

    这里注意一下Oracle选择参数文件的顺序。

    在oracle10G里,Oracle首选spfile<sid>.ora文件作为启动参数文件;如果该文件不存在,Oracle选择spfile.ora文件;如果前者都不存在,Oracle将会选择init<sid>.ora文件;如果以上3个文件都不存在,Oracle将无法创建和启动instance。

    用户可以在SQL*PLUS中通过show patameter spfile命令来检查数据库是否使用了spfile文件,如果value不为Null,则数据库使用了spfile文件;

    SQL> show parameter spfile

    NAME TYPE VALUE

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

    spfile string /opt/ora10g/product/10.2.0/db_1/dbs/spfileORCL.ora

    注意:

    ORACLE_HOME= /opt/ora10g/product/10.2.0/db_1

    ORACLE_SID=ORCL

    这时候也可以从操作系统查看启动了的后台进程:

    [oracle@czjie ~]$ ps -ef|grep ora_

    oracle 2787 1 0 22:20 ? 00:00:01 ora_pmon_ORCL

    oracle 2789 1 0 22:20 ? 00:00:00 ora_psp0_ORCL

    oracle 2791 1 0 22:20 ? 00:00:00 ora_mman_ORCL

    oracle 2793 1 0 22:20 ? 00:00:00 ora_dbw0_ORCL

    oracle 2795 1 0 22:20 ? 00:00:00 ora_lgwr_ORCL

    oracle 2797 1 0 22:20 ? 00:00:00 ora_ckpt_ORCL

    oracle 2799 1 0 22:20 ? 00:00:00 ora_smon_ORCL

    oracle 2801 1 0 22:20 ? 00:00:00 ora_reco_ORCL

    oracle 2803 1 0 22:20 ? 00:00:00 ora_cjq0_ORCL

    oracle 2805 1 0 22:20 ? 00:00:00 ora_mmon_ORCL

    oracle 2807 1 0 22:20 ? 00:00:00 ora_mmnl_ORCL

    oracle 2809 1 0 22:20 ? 00:00:00 ora_d000_ORCL

    oracle 2811 1 0 22:20 ? 00:00:00 ora_s000_ORCL

    oracle 3005 2818 0 22:48 pts/2 00:00:00 grep ora_

    SQL> shutdown immediate;

    ORA-01507: database not mounted

    ORACLE instance shut down.

    现在更名spfile<sid>.ora文件,此后Oracle将选择spfile.ora文件来启动数据库:

    [oracle@czjie dbs]$ ls

    hc_ORCL.dat init.ora lkORCL spfileORCL.ora spfileORCL.ora.bak0

    initdw.ora initORCL.ora orapwORCL spfileORCL.ora.bak

    [oracle@czjie dbs]$ mv spfileORCL.ora spfile.ora

    [oracle@czjie dbs]$ ls

    hc_ORCL.dat init.ora lkORCL spfile.ora spfileORCL.ora.bak0

    initdw.ora initORCL.ora orapwORCL spfileORCL.ora.bak

    SQL> startup nomount

    ORACLE instance started.

    Total System Global Area 218103808 bytes

    Fixed Size 1266680 bytes

    Variable Size 121637896 bytes

    Database Buffers 92274688 bytes

    Redo Buffers 2924544 bytes

    SQL> show parameter spfile

    NAME TYPE VALUE

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

    spfile string /opt/ora10g/product/10.2.0/db_1/dbs/spfile.ora

    SQL> shutdown immediate;

    ORA-01507: database not mounted

    ORACLE instance shut down.

    SQL>

    再更名spfile.ora文件,此时Oracle将选择init<sid>.ora文件启动数据库:

    [oracle@czjie dbs]$ mv spfile.ora spfile.ora.bak

    [oracle@czjie dbs]$ ls

    hc_ORCL.dat init.ora lkORCL spfile.ora.bak spfileORCL.ora.bak0

    initdw.ora initORCL.ora orapwORCL spfileORCL.ora.bak

    SQL> startup nomount

    ORACLE instance started.

    Total System Global Area 218103808 bytes

    Fixed Size 1266680 bytes

    Variable Size 71306248 bytes

    Database Buffers 142606336 bytes

    Redo Buffers 2924544 bytes

    SQL> show parameter spfile

    NAME TYPE VALUE

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

    spfile string

    SQL> shutdown immediate;

    ORA-01507: database not mounted

    ORACLE instance shut down.

    如果这3个文件都不在,Oracle将无法启动:

    [oracle@czjie dbs]$ mv initORCL.ora initORCL.ora.bak

    ......

    SQL> startup

    ORA-01078: failure in processing system parameters

    LRM-00109: could not open parameter file '/opt/ora10g/product/10.2.0/db_1/dbs/initORCL.ora'

    可以看到这里出现了错误,报告无法找到参数文件,init<sid>.ora是Oracle最后一个查找的参数文件。

    在Oracle整个启动过程中,参数文件是在应用程序中的硬代码,按照如上顺序进行查找,不能改变Oracle的搜索路径及行为,但是如果参数文件不在响应的位置,在Linux/UNIX系统上,可以通过符号链接来进行重定位。

    在参数文件中,通常需要最好的参数是db_name,设置了这个参数后,数据库实例就可以启动,来看一个简单的测试。

    随便命名一个实例(测试来自远Linux,使用于Linux/UNIX,对于Windows平台,需要通过oradmin工具创建实例),然后尝试启动到nomount状态:

    [oracle@czjie ~]$ export ORACLE_SID=czjie

    [oracle@czjie ~]$ sqlplus "/ as sysdba"

    SQL*Plus: Release 10.2.0.4.0 - Production on Fri Nov 11 23:04:03 2011

    Copyright (c) 1982, 2007, Oracle. All Rights Reserved.

    Connected to an idle instance.

    SQL> startup nomount

    ORA-01078: failure in processing system parameters

    LRM-00109: could not open parameter file '/opt/ora10g/product/10.2.0/db_1/dbs/initczjie.ora'

    参数文件查找失败会给出提示信息,创建一个最简单的参数文件,然后就可以启动实例:

    [oracle@czjie ~]$ cd $ORACLE_HOME/dbs/

    [oracle@czjie dbs]$ vi initczjie.ora

    #添加下面内容

    db_name=czjie

    [oracle@czjie dbs]$ ls

    hc_ORCL.dat init.ora orapwORCL spfileORCL.ora.bak0

    initczjie.ora initORCL.ora.bak spfile.ora.bak

    initdw.ora lkORCL spfileORCL.ora.bak

    SQL> startup nomount

    ORACLE instance started.

    Total System Global Area 113246208 bytes

    Fixed Size 1266080 bytes

    Variable Size 58723936 bytes

    Database Buffers 50331648 bytes

    Redo Buffers 2924544 bytes

    缺省情况下,如果不设置,background_dump_dest目录(警报日志文件alert_<sid>.log的存放地点)位于$ORACLE_HOME/edbms/log目录下:

    SQL> show parameter background_dump

    NAME TYPE VALUE

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

    background_dump_dest string /opt/ora10g/product/10.2.0/db_

    1/rdbms/log

    顺便看看其他几个缺省路径的地址:

    SQL> show parameter dump_dest

    NAME TYPE VALUE

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

    background_dump_dest string /opt/ora10g/product/10.2.0/db_1/rdbms/log

    core_dump_dest string /opt/ora10g/product/10.2.0/db_1/dbs

    user_dump_dest string /opt/ora10g/product/10.2.0/db_1/rdbms/log

    SQL> show parameter control_files

    NAME TYPE VALUE

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

    control_files string /opt/ora10g/product/10.2.0/db_1/dbs/cntrlczjie.dbf

    收录简单启动实例日志工大家参考:

    [oracle@czjie ~]$ cd $ORACLE_HOME/dbs/

    [oracle@czjie dbs]$ vi initczjie.ora

    [oracle@czjie dbs]$ ls

    hc_ORCL.dat init.ora orapwORCL spfileORCL.ora.bak0

    initczjie.ora initORCL.ora.bak spfile.ora.bak

    initdw.ora lkORCL spfileORCL.ora.bak

    [oracle@czjie dbs]$ cd ~

    [oracle@czjie ~]$ clear

    [oracle@czjie ~]$ cat $ORACLE_HOME/rdbms/log/alert_czjie.log

    Fri Nov 11 23:08:24 2011

    Starting ORACLE instance (normal)

    LICENSE_MAX_SESSION = 0

    LICENSE_SESSIONS_WARNING = 0

    Shared memory segment for instance monitoring created

    Picked latch-free SCN scheme 2

    Using LOG_ARCHIVE_DEST_1 parameter default value as /opt/ora10g/product/10.2.0/db_1/dbs/arch

    Autotune of undo retention is turned off.

    LICENSE_MAX_USERS = 0

    SYS auditing is disabled

    ksdpec: called for event 13740 prior to event group initialization

    Starting up ORACLE RDBMS Version: 10.2.0.4.0.

    System parameters with non-default values:

    db_name = czjie

    PSP0 started with pid=3, OS id=3167

    PMON started with pid=2, OS id=3165

    MMAN started with pid=4, OS id=3169

    DBW0 started with pid=5, OS id=3171

    LGWR started with pid=6, OS id=3173

    CKPT started with pid=7, OS id=3175

    SMON started with pid=8, OS id=3177

    RECO started with pid=9, OS id=3179

    MMON started with pid=10, OS id=3181

    MMNL started with pid=11, OS id=3183

    这样,就通过了最少的参数需求启动了Oracle实例。

    在使用RMAN(Recovery Manager)时存在更为特殊的情况,Oracle允许在不存在参数文件的情况下启动一个实例,数据库db_name会被缺省命名为DUMMY:

    [oracle@czjie ~]$ rman target /

    Recovery Manager: Release 10.2.0.4.0 - Production on Fri Nov 11 23:17:30 2011

    Copyright (c) 1982, 2007, Oracle. All rights reserved.

    connected to target database (not started)

    RMAN> startup nomount;

    startup failed: ORA-01078: failure in processing system parameters

    LRM-00109: could not open parameter file '/opt/ora10g/product/10.2.0/db_1/dbs/initORCL.ora'

    starting Oracle instance without parameter file for retrival of spfile

    Oracle instance started

    Total System Global Area 159383552 bytes

    Fixed Size 1266344 bytes

    Variable Size 54529368 bytes

    Database Buffers 100663296 bytes

    Redo Buffers 2924544 bytes

    RMAN> host;

    [oracle@czjie ~]$ sqlplus "/ as sysdba"

    SQL*Plus: Release 10.2.0.4.0 - Production on Fri Nov 11 23:18:07 2011

    Copyright (c) 1982, 2007, Oracle. All Rights Reserved.

    Connected to:

    Oracle Database 10g Enterprise Edition Release 10.2.0.4.0 - Production

    With the Partitioning, OLAP, Data Mining and Real Application Testing options

    SQL> show parameter db_name

    NAME TYPE VALUE

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

    db_name string DUMMY

    此时警告日志文件中会记录如下信息:

    Starting up ORACLE RDBMS Version: 10.2.0.4.0.

    System parameters with non-default values:

    sga_target = 159383552

    compatible = 10.2.0.4.0

    _dummy_instance = TRUE

    remote_login_passwordfile= EXCLUSIVE

    db_name = DUMMY

    PMON started with pid=2, OS id=3214

    PSP0 started with pid=3, OS id=3216

    MMAN started with pid=4, OS id=3218

    DBW0 started with pid=5, OS id=3220

    LGWR started with pid=6, OS id=3222

    CKPT started with pid=7, OS id=3224

    RECO started with pid=9, OS id=3228

    MMNL started with pid=11, OS id=3232

    SMON started with pid=8, OS id=3226

    MMON started with pid=10, OS id=3230

    在实例创建以后,Oracle就可以逐步导航,完成数据库的加载、打开等工作。

    1.2 启动数据库到mount状态

    启动到nomount 状态以后,Oracle就可以从参数文件中获取控制文件的位置信息,这一部分信息在参数文件中的记录类似如下所示(Oracle缺省会创建3个控制文件,这3个控制文件的内容完全一致,是Oracle为了安全而才用的景象手段,在生产环境中,通常应该将3个控制文件存放在不同的物理硬盘上,避免因为介质故障而同时损坏3个控制文件):

    control_files = /opt/ora10g/oradata/ORCL/control01.ctl, /opt/ora10g/oradata/ORCL/control02.ctl, /opt/ora10g/oradata/ORCL/control03.ctl

    在nomount状态,可以查询v$parameter视图,获取控制文件信息,这部分信息来自启动的参数文件;当数据库mount之后,可以查询v$controlfile视图获得关于控制文件的信息,此时,这部分信息来自控制文件:

    SQL> startup nomount

    ORACLE instance started.

    Total System Global Area 218103808 bytes

    Fixed Size 1266680 bytes

    Variable Size 121637896 bytes

    Database Buffers 92274688 bytes

    Redo Buffers 2924544 bytes

    SQL> select * from v$controlfile;

    no rows selected

    SQL> show parameter control_file

    NAME TYPE VALUE

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

    control_file_record_keep_time integer 7

    control_files string /opt/ora10g/oradata/ORCL/contr

    ol01.ctl, /opt/ora10g/oradata/

    ORCL/control02.ctl, /opt/ora10

    g/oradata/ORCL/control03.ctl

    SQL> alter database mount;

    Database altered.

    SQL> select * from v$controlfile;

    STATUS

    -------

    NAME

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

    IS_ BLOCK_SIZE FILE_SIZE_BLKS

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

    /opt/ora10g/oradata/ORCL/control01.ctl

    NO 16384 430

    /opt/ora10g/oradata/ORCL/control02.ctl

    NO 16384 430

    STATUS

    -------

    NAME

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

    IS_ BLOCK_SIZE FILE_SIZE_BLKS

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

    /opt/ora10g/oradata/ORCL/control03.ctl

    NO 16384 430

    在mount数据库的过程中,Oracle需要找到控制文件并锁定控制文件。如果控制文件全部丢失此时就会报出如下错误:

    [oracle@czjie ~]$ cd /opt/ora10g/oradata/ORCL/

    [oracle@czjie ORCL]$ ls

    control01.ctl redo01.log sysaux01.dbf undotbs01.dbf

    control02.ctl redo02.log system01.dbf users01.dbf

    control03.ctl redo03.log temp01.dbf

    [oracle@czjie ORCL]$ mv control01.ctl control01.ctl.bak

    [oracle@czjie ORCL]$ ls

    control01.ctl.bak redo01.log sysaux01.dbf undotbs01.dbf

    control02.ctl redo02.log system01.dbf users01.dbf

    control03.ctl redo03.log temp01.dbf

    ……

    SQL> startup

    ORACLE instance started.

    Total System Global Area 218103808 bytes

    Fixed Size 1266680 bytes

    Variable Size 121637896 bytes

    Database Buffers 92274688 bytes

    Redo Buffers 2924544 bytes

    ORA-00205: error in identifying control file, check alert log for more info

    这时候alert<sid>.log文件中通常会记录更为详细的信息:

    Sat Nov 12 00:04:11 2011

    ORA-00202: control file: '/opt/ora10g/oradata/ORCL/control01.ctl'

    ORA-27037: unable to obtain file status

    Linux Error: 2: No such file or directory

    Additional information: 3

    因为Oracle的3个(缺省的)控制文件内容完全相同,如果只是损失了其中1~2个,可以复制完好的控制文件,更改为相应的名称,就可以启动数据库;如果丢失了所有的控制文件,那么就需要恢复或重建控制文件来打开数据库。

    在正常mount数据库的过程中,数据库的警报日志文件仅记录如下信息:

    Sat Nov 12 00:10:34 2011

    Successful mount of redo thread 1, with mount id 1294793846

    Sat Nov 12 00:10:34 2011

    Database mounted in Exclusive Mode

    Completed: ALTER DATABASE MOUNT

    在这一步骤中,数据库需要计算mount id并将其记录在控制文件中,然后开始启动Heartbeat(心跳),每3秒更新一次控制文件。可以用一下命令间隔3秒转储2次控制文件信息:

    SQL> alter session set events 'immediate trace name CONTROLF level 10';

    Session altered.

    在linux上用diff命令比较两个文件,可以发现,控制文件在Mount状态下发生变化的只有这个Heartbeat:

    [oracle@czjie ORCL]$ diff orcl_ora_25542.trc orcl_ora_25706.tac

    64c63

    <heartbeat:588983634 mount id:1408096182

    >heartbeat:588983636 mount id: 1408096182

    HeartBeat 表明实例已经被特定例程所mount,这个属性主要用于OPS/RAC环境。但是Heartbeat在单实例环境中同样存在。

    可以从一个内部表(需要以SYS用户登录)中查询到当前的Heartbeat值:

    SQL> select cphbt from x$kcccp;

    从Oracle 9i 开始,Oracle在数据库内部通过等待事件control file heartbeat来记录这个事件的相关等待:

    SQL> select event#,name from v$event_name where name like '%heart%';

    EVENT# NAME

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

    282 ASM mount : wait for heartbeat

    423 control file heartbeat

    了解了启动的各个步骤,也就可以在发生问题的时候,快速定位,准确判断,从而快速解决问题。

    启动到mount状态,数据库必须具备的另外一个重要文件就是口令文件,该文件位于$ORACLE_HOEM/dbs目录下,缺省的名称为orapw<sid>。

    口令文件中存放sysdba/sysoper用户的用户名及口令:

    [oracle@czjie dbs]$ strings orapwORCL

    ]\[Z

    ORACLE Remote Password file

    INTERNAL

    239C08867B270ADC

    3E378BE1E39BBBA6

    在数据库没有启动之前,数据库内建用户是无法通过数据库本身来验证身份的,通过口令文件,Oracle可以实现对用户的身份验证,在数据库为启动之前登陆,进而启动数据库。

    如果丢失了口令文件,在mount阶段就会出现错误:

    ORA-01990: error opening password file '/opt/ora10g/product/10.2.0/dbs/orapw'

    ORA-27037: unable to obtain file status

    Linux Error: 2: No such file or directory

    Additional information: 3

    对于口令文件,Oracle缺省查找orapw<sid>文件,如果该文件不存在,则继续查找orapw文件,如果两个文件都不存在,则数据库将会出现错误。

    如果口令文件丢失,通过orapw工具即可重建,所以通常的备份策略中可以不必包含口令文件:

    [oracle@czjie dbs]$ orapwd

    Usage: orapwd file=<fname> password=<password> entries=<users> force=<y/n> nosysdba=<y/n>

    where

    file - name of password file (mand),

    password - password for SYS (mand),

    entries - maximum number of distinct DBA,

    force - whether to overwrite existing file (opt),

    nosysdba - whether to shut out the SYSDBA logon (opt for Database Vault only).

    There are no spaces around the equal-to (=) character.

    初始化参数文件remote_login_passwordfile和口令文件有关,限于篇幅,本文不再过多介绍。

    通过在Linux/UNIX平台下,在$ORACLE_HOME/dbs目录下,还会存在另外一个文件,该文件命名规则为lk<SID>,lk指lock,该文件在数据库启动时创建,用于操作系统对数据库的锁定。当数据库启动时获得锁定,数据库关闭时释放。

    有时在系统出现异常时,可能数据库已经关闭,但是锁定并未释放,或者因为后台进程未正常停止等原因,会导致下次数据库无法启动,相关的错误信息类似如下:

    Sun Apr 30 06:08:58 2011

    ALTER DATABASE MOUNT

    Sun Apr 30 06:08:58 2011

    scumnt: failed to lock /export/product/oracle/app/dbs/lkBILL exclusive

    Sun Apr 30 06:08:58 2011

    ORA-09968: scumnt: unable to lock file

    SVR4 Error: 11: Resource temporarily unavailable

    Additional information: 20169

    该文件内容通常只有一行,提示不要删除,该文件仅仅用于锁定:

    bash-2.03$ more lkBILL

    DO NOT DELETE THIS FILE!

    这样的文件很少出现,通常在正常关闭数据库后即可重新启动。

    1.3 启动数据库open阶段

    由于控制文件中记录了数据库中数据文件、日志文件的位置信息、检查点信息等重要信息,所以在数据库的open阶段,Oracle可以根据控制文件中记录的这些信息找到这些文件,然后进行检查点及完整性检查。

    如果不存在问题就可以启动数据库,如果存在不一致或文件丢失则需要进行恢复。

    进一步地说,实际上在数据库open的过程中,Oracle进行的检查中包括以下两项:

    第一次检查数据文件头中的检查点技术(Checkpoint cnt)是否和控制文件中的检查点(CheckPoint Cnt)一致,此步骤检查用意确认数据文件是否来自同一版本,而不是从备份中恢复而来(因为Checkpoint Cnt不会被冻结,会一直被修改)。

    下面通过一个简单的测试来说明一下Checkpoint Cnt的作用。

    定位oracle实例的当前跟踪文件名及路径

    SQL> select u_dump.value || '/' || db_name.value || '_ora_' || v$process.spid || nvl2(v$process.traceid, '_' || v$process.traceid, null )|| '.trc' "Trace File" from v$parameter u_dump cross join v$parameter db_name cross join v$process join v$session on v$process.addr = v$session.paddr where u_dump.name = 'user_dump_dest' and db_name.name = 'db_name' and v$session.audsid=sys_context('userenv','sessionid');

    Trace File

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

    /opt/ora10g/admin/ORCL/udump/ORCL_ora_2754.trc

    首先通过如下命令在不同条件下转储控制文件,第一步转储正常状态下的控制文件:

    SQL> alter session set events 'immediate trace name controlf level 12';

    Session altered.

    将系统表空间置于热备份状态(热备状态会冻结表空间数据文件的检查点):

    SQL> alter tablespace system begin backup;

    Tablespace altered.

    再来转储控制文件:

    SQL> alter session set events 'immediate trace name controlf level 12';

    Session altered.

    手工执行检查点并转储控制文件:

    SQL> alter system checkpoint;

    System altered.

    SQL> alter session set events 'immediate trace name controlf level 12';

    Session altered.

    结束表空间的热备状态,再次转储控制文件:

    SQL> alter tablespace system end backup;

    Tablespace altered.

    SQL> alter session set events 'immediate trace name controlf level 12';

    Session altered.

    简要地来看一下跟踪文件(仅研究system表空间记录)。

    (1) 正常情况下转储控制文件。

    ***************************************************************************

    DATA FILE RECORDS

    ***************************************************************************

    (size = 428, compat size = 428, section max = 100, section in-use = 4,

    last-recid= 53, old-recno = 0, last-recno = 0)

    (extent = 1, blkno = 11, numrecs = 100)

    DATA FILE #1:

    (name #7) /opt/ora10g/oradata/ORCL/system01.dbf

    creation size=0 block size=8192 status=0xe head=7 tail=7 dup=1

    tablespace 0, index=1 krfil=1 prev_file=0

    unrecoverable scn: 0x0000.00000000 01/01/1988 00:00:00

    Checkpoint cnt:106 scn: 0x0000.000d845f 11/14/2011 15:24:50

    Stop scn: 0xffff.ffffffff 11/14/2011 14:31:00

    Creation Checkpointed at scn: 0x0000.00000009 06/30/2005 19:10:11

    ……

    注意这里记录的检查点计数器及SCN;

    (2) 执行Begin Backup以后的。

    注意到Checkpoing cnt 增加了1,对表空间执行Begin Backup 会触发一次表空间检查点:

    ***************************************************************************

    DATA FILE RECORDS

    ***************************************************************************

    (size = 428, compat size = 428, section max = 100, section in-use = 4,

    last-recid= 53, old-recno = 0, last-recno = 0)

    (extent = 1, blkno = 11, numrecs = 100)

    DATA FILE #1:

    (name #7) /opt/ora10g/oradata/ORCL/system01.dbf

    creation size=0 block size=8192 status=0xe head=7 tail=7 dup=1

    tablespace 0, index=1 krfil=1 prev_file=0

    unrecoverable scn: 0x0000.00000000 01/01/1988 00:00:00

    Checkpoint cnt:107 scn: 0x0000.000d8489 11/14/2011 15:26:11

    Stop scn: 0xffff.ffffffff 11/14/2011 14:31:00

    Creation Checkpointed at scn: 0x0000.00000009 06/30/2005 19:10:11

    ……

    可以注意到检查点计数器随之增加。

    (3) 执行手工检查点。

    在表空间热备份模式下,手工执行检查点后,可以看到,此时Checkpoint cnt增加,但是scn不在改变。这是由于表空间处于热备份模式,数据文件检查点会被冻结(热备模式下,数据库会生成额外的Redo日志,在后面文章中会有详细介绍)。

    ***************************************************************************

    DATA FILE RECORDS

    ***************************************************************************

    (size = 428, compat size = 428, section max = 100, section in-use = 4,

    last-recid= 53, old-recno = 0, last-recno = 0)

    (extent = 1, blkno = 11, numrecs = 100)

    DATA FILE #1:

    (name #7) /opt/ora10g/oradata/ORCL/system01.dbf

    creation size=0 block size=8192 status=0xe head=7 tail=7 dup=1

    tablespace 0, index=1 krfil=1 prev_file=0

    unrecoverable scn: 0x0000.00000000 01/01/1988 00:00:00

    Checkpoint cnt:108 scn: 0x0000.000d8489 11/14/2011 15:26:11

    Stop scn: 0xffff.ffffffff 11/14/2011 14:31:00

    Creation Checkpointed at scn: 0x0000.00000009 06/30/2005 19:10:11

    ……

    (4) End Backup后的情况

    此时数据库头的冻结被取消,SCN开始变化:

    ***************************************************************************

    DATA FILE RECORDS

    ***************************************************************************

    (size = 428, compat size = 428, section max = 100, section in-use = 4,

    last-recid= 53, old-recno = 0, last-recno = 0)

    (extent = 1, blkno = 11, numrecs = 100)

    DATA FILE #1:

    (name #7) /opt/ora10g/oradata/ORCL/system01.dbf

    creation size=0 block size=8192 status=0xe head=7 tail=7 dup=1

    tablespace 0, index=1 krfil=1 prev_file=0

    unrecoverable scn: 0x0000.00000000 01/01/1988 00:00:00

    Checkpoint cnt:109 scn: 0x0000.000d849e 11/14/2011 15:26:49

    Stop scn: 0xffff.ffffffff 11/14/2011 14:31:00

    Creation Checkpointed at scn: 0x0000.00000009 06/30/2005 19:10:11

    ……

    这就是检查点计数器及其在不同模式下的变化。

    如果检查点计数检查通过,则数据库进行第二次检查。第二次检查数据文件头的开始SCN和控制文件中记录的该文件的结束SCN是否一致,如果控制文件中记录的结束SCN等于数据文件头的开始SCN,则不需要对那个文件进行恢复。

    对每个数据文件都完成检查后,打开数据库,锁定数据文件,同时将每个数据文件的结束SCN设置为无穷大。

    看一下一下测试,如果数据库中的某个文件丢失:

    [oracle@czjie ORCL]$ pwd

    /opt/ora10g/oradata/ORCL

    [oracle@czjie ORCL]$ ls

    control01.ctl control03.ctl redo02.log sysaux01.dbf temp01.dbf users01.dbf

    control02.ctl redo01.log redo03.log system01.dbf undotbs01.dbf

    [oracle@czjie ORCL]$ mv users01.dbf users01.dbf.bak

    [oracle@czjie ORCL]$

    那么在启动数据库的时候,在Open阶段,Oracle才会检查这个文件的存在性,如果文件不存在,数据库会给出错误信息,停止启动:

    SQL> startup nomount;

    ORACLE instance started.

    Total System Global Area 218103808 bytes

    Fixed Size 1266680 bytes

    Variable Size 121637896 bytes

    Database Buffers 92274688 bytes

    Redo Buffers 2924544 bytes

    SQL> alter database mount;

    Database altered.

    SQL> alter database open;

    alter database open

    *

    ERROR at line 1:

    ORA-01157: cannot identify/lock data file 4 - see DBWR trace file

    ORA-01110: data file 4: '/opt/ora10g/oradata/ORCL/users01.dbf'

    注意:仅在open阶段,Oracle才尝试打开并锁定数据文件,如果丢失或出现问题,则会给出错误提示。这时候就需要dba的介入进行处理,根据不同情况进行相应的恢复。

    现在来看看alert<sid>.log文件中记录的open过程中提示的错误信息:

    Mon Nov 14 15:50:10 2011

    alter database open

    Mon Nov 14 15:50:10 2011

    Errors in file /opt/ora10g/admin/ORCL/bdump/orcl_dbw0_3625.trc:

    ORA-01157: cannot identify/lock data file 4 - see DBWR trace file

    ORA-01110: data file 4: '/opt/ora10g/oradata/ORCL/users01.dbf'

    ORA-27037: unable to obtain file status

    Linux Error: 2: No such file or directory

    Additional information: 3

    ORA-1157 signalled during: alter database open...

    在数据库出现问题的时候,提示中给出的可能是不完整的信息,而警报日志中则记录了完整的错误过程和错误号。所以当数据库出现故障时,应该优先检查alert_<sid>.log,从中发现关于故障的详细信息。

    在完成数据库的验证和恢复过程后,数据库处于抑制的状态,数据库还需要进行一系列的处理过程:将undo段在线等操作,然后数据库可以提供访问,同时SMON可以开始进行事务回滚等。

    在启动日志里,我们经常可以看到这样一行:

    Database Characterset is ZHS16GBK

    在每次数据库的启动过程中,Oracle都需要判断控制文件中记录的字符集和数据库中的字符集是否相符,如果相符,则记录上一行日志;如果不相符,则以数据库中的字符集为准更新控制文件中的字符集记录,类似的日志如下:

    Updating character set in controlfile to ZHS16CGB231280

    提示:在Oracle 8i之前,可以通过Update props$表的方式修改字符集,从Oracle 8i开始,切忌绝对不要使用同样的方式修改字符集。

    如果细致一些,启动日志的每条信息都是指的研究的。

    1.4.深入分析

    现在我们再深入一下,研究在数据库Open的过程中。Oracle实际需要执行的操作。

    1.4.1.获得数据库Open的跟踪文件

    数据库的信息都是存放在数据文件当中的,但是当数据库尚未打开之前,Oracle是无法获得这部分数据的,那么Oracle是怎样完成这个从数据文件到内存的初始化过程的呢?

    [oracle@czjie ~]$ sqlplus / as sysdba

    SQL*Plus: Release 10.2.0.4.0 - Production on Mon Nov 21 20:41:16 2011

    Copyright (c) 1982, 2007, Oracle. All Rights Reserved.

    Connected to an idle instance.

    SQL> startup mount;

    ORACLE instance started.

    Total System Global Area 218103808 bytes

    Fixed Size 1266680 bytes

    Variable Size 121637896 bytes

    Database Buffers 92274688 bytes

    Redo Buffers 2924544 bytes

    Database mounted.

    SQL> alter session set sql_trace=true;

    Session altered.

    SQL> alter database open;

    Database altered.

    这里通过SQL_TRACE获得一个跟踪文件,跟踪文件里将记录从mount到open的过程中,Oracle所执行的后台操作。

    1.4.2 .bootstrap$及数据库初始化过程

    SQL> select u_dump.value || '/' || db_name.value || '_ora_' || v$process.spid || nvl2(v$process.traceid, '_' || v$process.traceid, null )|| '.trc' "Trace File" from v$parameter u_dump cross join v$parameter db_name cross join v$process join v$session on v$process.addr = v$session.paddr where u_dump.name = 'user_dump_dest' and db_name.name = 'db_name' and v$session.audsid=sys_context('userenv','sessionid');

    Trace File

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

    /opt/ora10g/admin/ORCL/udump/ORCL_ora_2932.trc

    [oracle@czjie ~]$ tkprof /opt/ora10g/admin/ORCL/udump/orcl_ora_2932.trc /opt/ora10g/orcl_ora_2932.txt

    TKPROF: Release 10.2.0.4.0 - Production on Mon Nov 21 21:15:43 2011

    Copyright (c) 1982, 2007, Oracle. All rights reserved.

    通过tkprof格式化跟踪文件之后,来看一下其中的内容。首先来参考跟踪文件的前面部分,这事第一个对象的创建:

    create table bootstrap$ ( line# number not null, obj#

    number not null, sql_text varchar2(4000) not null) storage (initial

    50K objno 56 extents (file 1 block 377))

    这一步骤中,实际上Oracle是在内存中创建bootstrap$结构,然后从数据文件的file 1 block 377读取数据导内存中,完成第一次初始化。

    提示:file 1 block 377字句是内部语句,改语法对用户是不可用的。

    可以从数据库查询一下,file 1 block 377上存储的是什么对象:

    SQL> select segment_name,file_id,block_id from dba_extents where block_id=377;

    SEGMENT_NAME

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

    FILE_ID BLOCK_ID

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

    BOOTSTRAP$

    1 377

    I_DIR$INSTANCE_JOB_NAME

    3 377

    File 1 block 377 开始存放的正式bootstrap$对象。

    接下来在看trace文件中的内容,继续向下,Oracle执行的是:

    select line#, sql_text

    from

    bootstrap$ where obj# != :1

    在创建并从数据文件中装载了bootstrap$的内容之后,Oracle开始递归的从改表总读取信息,加载数据。那么bootstap$中记录的是什么信息呢?

    在数据库中,bootstrap$是一张实际存在的系统表:

    SQL> desc bootstrap$

    Name Null? Type

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

    LINE# NOT NULL NUMBER

    OBJ# NOT NULL NUMBER

    SQL_TEXT NOT NULL VARCHAR2(4000)

    来看一下这张表的具体内容:

    SQL> select * from bootstrap$ where line#<5;

    LINE# OBJ#

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

    SQL_TEXT

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

    -1 -1

    8.0.0.0.0

    0 0

    CREATE ROLLBACK SEGMENT SYSTEM STORAGE ( INITIAL 112K NEXT 1024K MINEXTENTS 1 M

    AXEXTENTS 32765 OBJNO 0 EXTENTS (FILE 1 BLOCK 9))

    2 2

    CREATE CLUSTER C_OBJ#("OBJ#" NUMBER) PCTFREE 5 PCTUSED 40 INITRANS 2 MAXTRANS 25

    LINE# OBJ#

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

    SQL_TEXT

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

    5 STORAGE ( INITIAL 136K NEXT 1024K MINEXTENTS 1 MAXEXTENTS 2147483645 PCTINCRE

    ASE 0 OBJNO 2 EXTENTS (FILE 1 BLOCK 25)) SIZE 800

    3 3

    CREATE INDEX I_OBJ# ON CLUSTER C_OBJ# PCTFREE 10 INITRANS 2 MAXTRANS 255 STORAGE

    ( INITIAL 64K NEXT 1024K MINEXTENTS 1 MAXEXTENTS 2147483645 PCTINCREASE 0 OBJN

    O 3 EXTENTS (FILE 1 BLOCK 49))

    4 4

    LINE# OBJ#

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

    SQL_TEXT

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

    CREATE TABLE TAB$("OBJ#" NUMBER NOT NULL,"DATAOBJ#" NUMBER,"TS#" NUMBER NOT NULL

    ,"FILE#" NUMBER NOT NULL,"BLOCK#" NUMBER NOT NULL,"BOBJ#" NUMBER,"TAB#" NUMBER,"

    COLS" NUMBER NOT NULL,"CLUCOLS" NUMBER,"PCTFREE$" NUMBER NOT NULL,"PCTUSED$" NUM

    BER NOT NULL,"INITRANS" NUMBER NOT NULL,"MAXTRANS" NUMBER NOT NULL,"FLAGS" NUMBE

    R NOT NULL,"AUDIT$" VARCHAR2(38) NOT NULL,"ROWCNT" NUMBER,"BLKCNT" NUMBER,"EMPCN

    T" NUMBER,"AVGSPC" NUMBER,"CHNCNT" NUMBER,"AVGRLN" NUMBER,"AVGSPC_FLB" NUMBER,"F

    LBCNT" NUMBER,"ANALYZETIME" DATE,"SAMPLESIZE" NUMBER,"DEGREE" NUMBER,"INSTANCES"

    NUMBER,"INTCOLS" NUMBER NOT NULL,"KERNELCOLS" NUMBER NOT NULL,"PROPERTY" NUMBER

    NOT NULL,"TRIGFLAG" NUMBER,"SPARE1" NUMBER,"SPARE2" NUMBER,"SPARE3" NUMBER,"SPA

    LINE# OBJ#

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

    SQL_TEXT

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

    RE4" VARCHAR2(1000),"SPARE5" VARCHAR2(1000),"SPARE6" DATE) STORAGE ( OBJNO 4 TA

    BNO 1) CLUSTER C_OBJ#(OBJ#)

    以上只查询了表中的5条记录,大家可以自行研究一下其他记录的内容。从这些语句中可以看出,bootstrap$中实际上只是记录了一些数据库系统基本对象的创建语句。Oracle通过bootstrap$进行引导,进一步创建相关的重要对象,从而启动了数据库。

    1.4.3. bootstrap$的重要性

    由上面的讨论可以知道bootstrap$表的重要,如果bootstrap$表发生损坏,则数据库将无法启动。读者可能遭遇以下案例,bootstrap$表被恶意修改,如果关闭数据库,之后将无法启动。

    以下此时仅为说明问题,请勿模仿,在未做好备份之前,请勿试验此类操作:

    SQL> col sql_text for a15;

    SQL> select * from bootstrap$ where rownum<2;

    LINE# OBJ# SQL_TEXT

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

    -1 -1 8.0.0.0.0

    SQL> update bootstrap$ set sql_text='9.0.0.0.0' where line#=-1;

    1 row updated.

    SQL> commit;

    Commit complete.

    SQL> select * from bootstrap$ where rownum<2;

    LINE# OBJ# SQL_TEXT

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

    -1 -1 9.0.0.0.0

    如果不关闭数据库,该修改是无影响的,bootstrap$也仅在数据库启动时才发挥其重要作用。继续往下看,如果bootstrap$损坏或者被恶意修改,在数据库启动时会受到如下错误:

    SQL> startup

    ORACLE instance started.

    Total System Global Area 218103808 bytes

    Fixed Size 1266680 bytes

    Variable Size 113249288 bytes

    Database Buffers 100663296 bytes

    Redo Buffers 2924544 bytes

    Database mounted.

    ORA-01092: ORACLE instance terminated. Disconnection forced

    进一步检查alert文件,可以发现更为详细的提示信息:

    Mon Nov 21 22:29:22 2011

    Errors in file /opt/ora10g/admin/ORCL/udump/orcl_ora_503.trc:

    ORA-00704: bootstrap process failure

    ORA-00702: bootstrap verison '9.0.0.0.0' inconsistent with version '8.0.0.0.0'

    Mon Nov 21 22:29:22 2011

    Error 704 happened during db open, shutting down database

    USER: terminating instance due to error 704

    Instance terminated by USER, pid = 503

    ORA-1092 signalled during: ALTER DATABASE OPEN..

    日志给出了详细的错误信息,在这种情况下,最好的方式是从备份中进行不完全恢复,如果没有备份,则恢复将会非常复杂和艰难。

  • 相关阅读:
    面对苹果的抄袭指责,小米到底有没有抄袭?
    如何用Ajax传一个数组数据
    为何日本人如此重视孩子的早餐问题
    常见编程语言对REPL支持情况小结
    坚持未必都是美德,也可能是无知
    PHP 5.4语法改进与弃用特性
    解决CI框架的Disallowed Key Characters错误提示
    如何抓取开了gzip的网页
    CodeIgniter自带的数据库类使用介绍
    Python内部变量与外部变量
  • 原文地址:https://www.cnblogs.com/czjie/p/2245084.html
Copyright © 2011-2022 走看看