《循序渐进Oracle:数据库管理、优化与备份恢复》一一1.3 数据库创建的脚本

简介:

本节书摘来自异步社区出版社《循序渐进Oracle:数据库管理、优化与备份恢复》一书中的第1章,第1.3节,作者:盖国强,更多章节内容可以访问云栖社区“异步社区”公众号查看。

1.3 数据库创建的脚本

循序渐进Oracle:数据库管理、优化与备份恢复
在DBCA的最后一个步骤,如果保存生成了创建数据库的脚本,则可以通过手工执行这些脚本,在命令行完成数据库的创建工作,这可以使我们摆脱图形界面的困扰,特别是在一些不易于运行图形界面的环境。此外,很多时候通过DBCA创建数据库可能会遇到一些错误,这些错误在图形界面下可能不易判断,但是通过命令行则要容易定位得多。

1.3.1 数据库创建脚本

现在通过数据库的创建脚本来深入地了解一下数据库的创建过程。按照上面的路径找到生成的数据库创建脚本。

C:\Oracle\admin\eygle\scripts>dir 
2007-01-05 15:32  <DIR>     . 
2007-01-05 15:32  <DIR>     .. 
2007-01-05 15:32       1,139 CreateDB.sql 
2007-01-05 15:32        600 CreateDBCatalog.sql 
2007-01-05 15:32        326 CreateDBFiles.sql 
2007-01-05 15:32        253 emRepository.sql 
2007-01-05 15:32        614 eygle.bat 
2007-01-05 15:32        698 eygle.sql 
2007-01-05 15:32       2,408 init.ora 
2007-01-05 15:33       1,108 postDBCreation.sql

在Linux/UNIX环境下,同样存在这样一系列的脚本:

[oracle@jumper scripts] $ pwd 
/opt/oracle/admin/eygle/scripts 
[oracle@jumper scripts] $ ll 
total 24 
-rw-r--r--  1 oracle  dba      713 Apr 24 2006 CreateDBCatalog.sql 
-rw-r--r--  1 oracle  dba      338 Apr 24 2006 CreateDBFiles.sql 
-rw-r--r--  1 oracle  dba      769 Apr 24 2006 CreateDB.sql 
-rwxr-xr-x  1 oracle  dba      628 Aug 18 2006 eygle.sh 
-rw-r--r--  1 oracle  dba     2764 Apr 24 2006 init.ora 
-rw-r--r--  1 oracle  dba      442 Apr 24 2006 postDBCreation.sql

1.3.2 创建的起点

如果通过手工执行脚本来创建数据库,需要执行的脚本为eygle.bat(在Linux/UNIX下是eygle.sh脚本),来看一下这个脚本的内容:

C:\Oracle\admin\eygle\scripts>type eygle.bat 
mkdir C:\oracle\10.2.0\cfgtoollogs\dbca\eygle 
mkdir C:\oracle\10.2.0\database 
mkdir C:\oracle\admin\eygle\adump 
mkdir C:\oracle\admin\eygle\bdump 
mkdir C:\oracle\admin\eygle\cdump 
mkdir C:\oracle\admin\eygle\dpdump 
mkdir C:\oracle\admin\eygle\pfile 
mkdir C:\oracle\admin\eygle\udump 
mkdir C:\oracle\flash_recovery_area 
mkdir C:\oracle\oradata 
set ORACLE_SID=eygle 
C:\oracle\10.2.0\bin\oradim.exe -new -sid EYGLE -startmode manual -spfile 
C:\oracle\10.2.0\bin\oradim.exe -edit -sid EYGLE -startmode auto -srvcstart system 
C:\oracle\10.2.0\bin\sqlplus /nolog @C:\oracle\admin\eygle\scripts\eygle.sql

这就是Oracle创建数据库的过程。

(1)建立一系列的目录。

注意,这里建立的bdump目录是Oracle重要的警告日志的存放地点,其缺省名称为alert_< sid >.log,我们应该定期检查该文件以发现数据库的故障或错误信息;在Oracle Database 11g中,这些文件的统一路径由参数diagnostic_dest定义。

第二个需要格外注意的是cfgtoollogsdbcaeygle目录,在创建数据库时,主要的日志文件或输出信息会记录在该目录中,通过检查这些文件可以用来诊断创建过程中出现的一些错误。

(2)设置ORACLE_SID环境变量。

(3)通过oradim创建并配置实例。

(4)通过sqlplus运行脚本开始创建数据库。

1.3.3 ORADIM工具的使用

ORADIM工具是Oracle在Windows上的一个命令行工具,用于手工进行Oracle服务的创建、修改、删除等工作。ORADIM的使用很简单,通过帮助文件可以看到常用的命令示例,此处不再赘述。

ORADIM在数据库恢复中也常被用到,很多朋友都问过这样的问题:在Windows上,如果系统崩溃了,可能数据库软件丢掉了,但是数据文件、控制文件、日志文件等都还在,该怎样来恢复Oracle数据库?

其实过程很简单,通常只要按原来的目录结构重新安装Oracle软件,然后通过ORADIM工具重建服务,就可以启动实例、加载数据库(当然,相关的参数文件和口令文件等需要保存在$ORACLE_HOMEdatabase目录中)。

来看以下过程,通过ORADIM创建一个服务后,实例会随之启动:

C:\>oradim -new -sid eygle 
实例已创建。

用net命令可以查看系统启动了哪些服务,看到Oracle的服务已经启动:

C:\>net start 
已经启动以下 Windows 服务: 
............... 
  OracleServiceeygle 
  Plug and Play 
  Print Spooler 
命令成功完成。

如果你的系统装了一些UNIX增强工具(强烈建议在Windows上安装UNIX增强工具集,熟悉常用UNIX命令),那么可以通过grep过滤一下:

C:\>net start |grep Oracle 
  OracleServiceeygle

使用ORADIM工具后,会在$ORACLE_HOMEdatabase目录下生成一个日志文件。

1.3.4 ORACLE_SID的含义

注意到在ORADIM创建服务之前,首先设置了ORACLE_SID:

set ORACLE_SID=eygle

在Linux/UNIX系统的创建中,同样要设置ORACLE_SID,不过Linux/UNIX上不存在服务这项内容,实例是可以通过参数文件直接启动的(注意:启动数据库实例还和一些内核参数有关,在产品环境中需要按手册认真设定)。

看一下Linux上正常情况下启动到nomount状态的过程:

[oracle@jumper oracle] $ cd $ORACLE_HOME/dbs 
[oracle@jumper dbs] $ ls 
initconner.ora init.ora lkCONNER orapwconner spfileconner.ora spfile.ora 
[oracle@jumper dbs] $ export ORACLE_SID=conner 
[oracle@jumper dbs] $ sqlplus "/ as sysdba" 

SQL> startup nomount 
ORACLE instance started. 

Total System Global Area  80811208 bytes 
Fixed Size          451784 bytes 
Variable Size       37748736 bytes 
Database Buffers      41943040 bytes 
Redo Buffers         667648 bytes

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

回顾一下前面的内容,注意到SID和ORACLE_SID已经多次出现,那么SID是什么?在数据库启动过程中又起到什么作用呢?

SID是System IDentifier的缩写,而ORACLE_SID就是Oracle System Identifier的缩写,在Oracle系统中,ORACLE_SID以环境变量的形式出现,在特定版本的Oracle软件安装(也就是ORACLE_HOME)下,当Oracle实例启动时,操作系统上fork的进程必须通过这个SID将实例与其他实例区分开来,这就是SID的作用。

我们知道Oracle的实例(instance)是由一块共享内存区域(SGA)和一组后台进程(background processes)共同组成;而后台进程正是数据库和操作系统进行交互的通道,这些进程的名称就是通过ORACLE_SID决定的。

实例的启动仅需要一个参数文件,而这个参数文件的名称就是由ORACLE_SID决定的。对于init文件,缺省的文件名称是init< ORACLE_SID >.ora,对于spfile文件,缺省的文件名为spfile< ORACLE_SID >.ora,Oracle依据ORACLE_SID来决定和寻找参数文件启动实例,参数文件的缺省位置为$ORACLE_HOME/dbs(Windows上为$ORACLE_HOMEdatabase目录)。

spfile从Oracle 9i开始引入并成为了缺省使用的参数文件,Oracle启动实例时按照以下顺序从缺省目录查找参数文件:

spfile.ora→spfile.ora →init.ora。
如果这3个文件都不存在,则Oracle实例将无法启动。

通过这些信息可以知道,在同一个ORACLE_HOME下,Oracle能够根据ORACLE_SID将实例区分开来;但是如果在不同的ORACLE_HOME下,Oracle将不屏蔽相同名称的ORACLE_SID,也就是说在同一台主机的不同ORACLE_HOME下,Oracle也是能够创建相同ORACLE_SID的实例的。

以下是一个测试。首先启动一个Oracle 8i下ORACLE_SID为eygle的实例:

$ export ORACLE_SID=eygle 
$ sqlplus "/ as sysdba" 
SQL*Plus: Release 8.1.7.0.0 - Production on Fri Feb 16 10:23:58 2007 
(c) Copyright 2000 Oracle Corporation. All rights reserved. 
Connected to an idle instance. 

SQL> startup nomount; 
ORACLE instance started. 
SQL> ! ps -ef|grep smon 
 oracle8 11092   1 0 10:24:02 ?    0:00 ora_smon_eygle

接下来又可以启动另外ORACLE_HOME下ORACLE_SID为eygle的实例:

$ export ORACLE_SID=eygle 
$ sqlplus "/ as sysdba" 
SQL*Plus: Release 9.2.0.4.0 - Production on Fri Feb 16 10:24:43 2007 
Copyright (c) 1982, 2002, Oracle Corporation. All rights reserved. 
Connected to an idle instance. 

SQL> startup nomount; 
ORACLE instance started. 
SQL> ! ps -ef|grep pmon_eygle 
 oracle9 11180   1 0 10:24:48 ?    0:00 ora_pmon_eygle 
 oracle8 11084   1 0 10:24:02 ?    0:00 ora_pmon_eygle

现在这同一台主机上就启动了两个相同名称的实例,在操作系统上,Oracle能够通过ID标识将共享内存或信号量区分开来:

$ ipcs -i 
IPC status from <running system> as of Fri Feb 16 10:30:02 CST 2007 
T     ID   KEY    MODE    OWNER  GROUP 
Message Queues: 
q     0  0x2e781d5 --rw-r--r--   root   root 
T     ID   KEY    MODE    OWNER  GROUP ISMATTCH 
Shared Memory: 
m    4096  0xabdc9b64 --rw-r----- oracle8   dba    12 
m    1025  0x79552064 --rw-r----- oracle9   dba    11 
Semaphores: 
s  1245184  0x79978bac --ra-r----- oracle8   dba 
s   458753  0xa0e9f594 --ra-r----- oracle9   dba

通过Oracle提供的一个小工具sysresv,我们可以找到对应于不同的ORACLE_SID,操作系统上创建的共享内存段ID(Shared Memory)和信号量ID(Semaphores)等信息。

$ sysresv -l eygle julia 

IPC Resources for ORACLE_SID "eygle" : 
Shared Memory: 
ID       KEY 
2560      0x79552064 
Semaphores: 
ID       KEY 
720896     0xa0e9f594 
Oracle Instance alive for sid "eygle" 

IPC Resources for ORACLE_SID "julia" : 
Shared Memory: 
ID       KEY 
514       0xab281214 
Semaphores: 
ID       KEY 
196610     0xa7645a54 
Oracle Instance alive for sid "julia"

在Linux/UNIX上,一个名为oratab的文件还记录有ORACLE_SID信息。在Solaris环境中,这个文件一般位于/var/opt/oracle目录下,在Linux及其他UNIX平台,这个文件一般位于/etc目录下。

该文件的主要内容如下:

# This file is used by ORACLE utilities. It is created by root.sh 
# and updated by the Database Configuration Assistant when creating a database. 
# A colon, ':', is used as the field terminator. A new line terminates 
# the entry. Lines beginning with a pound sign, '#', are comments. 
# 
# Entries are of the form: 
#  $ORACLE_SID: $ORACLE_HOME:<N|Y>: 
# The first and second fields are the system identifier and home 
# directory of the database respectively. The third filed indicates 
# to the dbstart utility that the database should , "Y", or should not, 
# "N", be brought up at system boot time. 
# 
# Multiple entries with the same $ORACLE_SID are not allowed. 
*:/opt/oracle/product/9.2.0:N

当执行dbstart脚本时,Oracle会根据这里记录的ORACLE_SID的< N|Y >的设置来决定是否启动相关实例。

与Linux/UNIX上的情况类似,Windows上的Oracle环境也依赖于服务而存在,如图1-24所示。

image

我们注意到Oracle环境的初始化是通过ORACLE.EXE eygle来完成的,至于实例和数据库是否随服务启动要依赖于注册表中的设置。

通过手动在命令行执行类似命令,可以初始化任意的Oracle应用环境,例如,以下命令就初始化了名为julia的运行时环境:

C:\>oracle julia 
Press CTRL-C to exit server:

此后就可以连接到这个环境启动实例:

C:\>set ORACLE_SID=julia 
C:\>set nls_lang=american_america.us7ascii 
C:\>sqlplus "/ as sysdba" 
SQL*Plus: Release 11.2.0.1.0 Production on Tue Aug 31 22:09:31 2010 
Copyright (c) 1982, 2010, Oracle. All rights reserved. 

Connected to an idle instance. 
SQL> startup 
ORA-01078: failure in processing system parameters 
LRM-00109: 无法打开参数文件 'D:\ORACLE\11.2.0\DATABASE\INITJULIA.ORA'

当然还需要创建参数文件和口令文件等:

C:\>cp c:\oracle\10.2.0\database\SPFILEEYGLE.ORA c:\Oracle\10.2.0\database\spfilejulia.ora 

C:\>orapwd file=c:\oracle\10.2.0\database\PWDjulia.ora password=oracle entries=5

此后,实例可以顺利启动,并可以挂接和打开数据库:

C:\>sqlplus "/ as sysdba" 
SQL*Plus: Release 10.2.0.1.0 - Production on 星期六 2月 17 10:13:10 2007 
Copyright (c) 1982, 2005, Oracle. All rights reserved. 
已连接到空闲例程。 

SQL> startup nomount; 
ORACLE 例程已经启动。 
SQL> set linesize 120 
SQL> show parameter instance_name 
NAME                 TYPE          VALUE 
------------------------------------ ---------------------- --------------- 
instance_name            string         julia 
SQL> show parameter db_name 
NAME                 TYPE          VALUE 
------------------------------- ------------------ ------------------------------ 
db_name               string         eygle 
SQL> alter database mount; 
数据库已更改。 
SQL> alter database open; 
数据库已更改。

如果在环境窗口中按下CTRL+C组合键退出,则数据库将异常中断。

总结一下,实际上不管在Windows还是Linux/UNIX环境下,ORACLE_SID的作用就是设置一个Oracle环境窗口,通过这个环境变量来标示和命名系统进程,此后Oracle的活动可以由此展开。

1.3.5 INSTANCE_NAME的含义及作用

作为Oracle数据库的重要组成部分INSTANCE也存在一个参数标识:INSTANCE_NAME。

INSTANCE_NAME是Oracle数据库的一个参数,在参数文件中定义,用于标示数据库实例的名称,其缺省值通常就是ORACLE_SID,但是不同的实例可以有相同的实例名。通过简单的参数文件复制,我们就可以在同一台服务器上创建多个具有相同instance_name参数设置的实例。

首先确认当前的参数文件:

bash-2.03$ cd $ORACLE_HOME/dbs 
bash-2.03$ ls initeygle.ora 
initeygle.ora

复制参数文件,更改名称:

bash-2.03$ cp initeygle.ora initjulia.ora

接下来通过导入新的ORACLE_SID我们就可以启动新的实例:

bash-2.03$ export ORACLE_SID=julia 
bash-2.03$ sqlplus "/ as sysdba" 
SQL*Plus: Release 9.2.0.4.0 - Production on Fri Feb 16 10:34:00 2007 
Copyright (c) 1982, 2002, Oracle Corporation. All rights reserved. 
Connected to an idle instance. 

SQL> startup nomount; 
ORACLE instance started.

现在ORACLE_SID为julia的实例已经启动,操作系统上的进程以julia名称标记:

bash-2.03$ ps -ef|grep pmon 
oracle  12396   1 0 16:30 ?    00:00:00 ora_pmon_julia 
oracle  16201   1 0 18:13 ?    00:00:00 ora_pmon_eygle 
oracle  16256 16219 0 18:14 pts/1  00:00:00 grep pmon
但是新实例的instance_name参数设置仍然是eygle:

SQL> show parameter instance_name 
NAME                 TYPE          VALUE 
------------------------------------ ---------------------- ----------------------- 
instance_name            string         eygle

总结一下,ORACLE_SID在这里用于标示进程,而instance_name则用来标示实例,两者可以具有不同的名称。但是如果不同往往带来歧义,不具备实际的意义,所以从Oracle Database 10g开始,缺省的情况下,Oracle将instance_name这个参数从参数文件中剔除,这样就能够尽量保证ORACLE_SID和instance_name的一致。

此外Oracle的监听器(listener)配置文件中的SID_NAME就是来自instance_name参数,监听器通过instance_name才能确定需要将连接请求注册到哪一个实例上。通常listener.ora文件中SID_NAME相关设置类似如下示例:

SID_LIST_LISTENER = 
  (SID_DESC = 
   (GLOBAL_DBNAME = eygle) 
   (ORACLE_HOME = /opt/oracle/product/9.2.0) 
   (SID_NAME = eygle) 
)

1.3.6 Oracle的口令文件

继续前面的脚本,在创建和启动了实例之后,Oracle开始调用eygle.sql脚本,我们将这个脚本分开来介绍。

这个脚本的最初部分是要求定义用户口令,然后使用定义的sys用户口令创建口令文件:

C:\Oracle\admin\eygle\scripts>type eygle.sql 
set verify off 
PROMPT specify a password for sys as parameter 1; 
DEFINE sysPassword = &1 
PROMPT specify a password for system as parameter 2; 
DEFINE systemPassword = &2 
PROMPT specify a password for sysman as parameter 3; 
DEFINE sysmanPassword = &3 
PROMPT specify a password for dbsnmp as parameter 4; 
DEFINE dbsnmpPassword = &4 
host C:\oracle\10.2.0\bin\orapwd.exe file=C:\oracle\10.2.0\database\PWDeygle.ora 
 password=&&sysPassword force=y

这里又引入了另外一个工具orapwd,这个工具在Linux/UNIX上同样存在,当口令文件丢失或损坏之后,可以通过这个工具重建口令文件,这个工具的语法为:

D:\oracle\11.2.0\BIN>orapwd 
Usage: orapwd file=<fname> entries=<users> force=<y/n> ignorecase=<y/n> nosysdba=<y/n> 

 where 
  file - name of password file (required), 
  password - password for SYS will be prompted if not specified at command line, 
  entries - maximum number of distinct DBA (optional), 
  force - whether to overwrite existing file (optional), 
  ignorecase - passwords are case-insensitive (optional), 
  nosysdba - whether to shut out the SYSDBA logon (optional Database Vault only).

 There must be no spaces around the equal-to (=) character.
注意:

force参数是Oracle 10g中增加的,ignorecase参数是11g新增加的。
Oracle在启动过程中,会在$ORACLE_HOME/dbs(Windows下相应的目录则是$ORACLE_HOMEdatabase)目录下查找口令文件,查找的顺序是首先检查orapw< ORACLE_SID >文件,如果不存在则查找orapw文件,如果orapw文件也不存在,就会报出如下错误:

SQL> startup force; 
ORACLE instance started. 

ORA-01990: error opening password file '/opt/oracle/product/9.2.0/dbs/orapw' 
ORA-27037: unable to obtain file status 
Linux Error: 2: No such file or directory 
Additional information: 3

口令文件丢失或损坏后,通常可以通过如下命令重建口令文件:

[oracle@jumper dbs] $ orapwd file=orapwhsjf password=oracle entries=5
在数据库没有启动之前,数据库内建用户是无法通过数据库来验证身份的,此时口令文件的作用就体现了出来。口令文件中存放了具有sysdba / sysoper身份用户的用户名及口令,Oracle允许用户通过口令文件验证,在数据库未启动之前登录,从而启动实例进而加载并打开数据库;而如果没有口令文件,在数据库未启动之前就只能通过操作系统认证方式来启动实例。在Oracle DataGuard环境中,要求主数据库和备用数据库的口令文件SYS用户密码相同,这时候经常会用到使用orapwd工具重建口令文件的技能。

Oracle通过一个初始化参数remote_login_passwordfile来限制口令文件的使用,通过这个参数可以设置用户登录时是否检查口令文件,以及有多少个数据库可以使用口令文件。这个参数有3个选项:EXCLUSIVE、SHARED和NONE。

当remote_login_passwordfile设置为NONE时,远程用户将不能通过sysdba/sysoper身份登录数据库:

SQL> show parameter pass 
NAME           TYPE    VALUE 
------------------------- ----------- ------------------------------ 
remote_login_passwordfile string   NONE

此时,通过远程连接会收到如下错误:

SQL> connect sys/oracle@hsjf as sysdba 
ERROR:ORA-01017: invalid username/password; logon denied

此处实际上是无法通过口令文件验证。

缺省的remote_login_passwordfile参数设置为exclusive,支持远程sysdba的登录操作:

SQL> alter system set remote_login_passwordfile=exclusive scope=spfile; 

System altered.

这个参数是静态参数,修改后重启数据库才能生效。当remote_login_passwordfile参数设置为exclusive时,可以通过远程以sysdba身份登录数据库:

E:\Oracle\ora92\bin>sqlplus /nolog 
SQL*Plus: Release 9.2.0.4.0 - 
Production on 星期四 4月 15 09:47:11 2004 
Copyright (c) 1982, 2002, Oracle Corporation. All rights reserved. 
SQL> connect sys/oracle@hsjf as sysdba 
已连接。 
SQL> show user 
USER 为"SYS"

当remote_login_passwordfile参数设置为shared时,则多个数据库可以共享一个口令文件,但是此时口令文件中只能存储SYS用户的口令,此时其他用户不能被授予sysdba身份:

SQL> select * from v$pwfile_users; 
USERNAME SYSDB SYSOP 
--------- ----- ----- 
SYS    TRUE  TRUE 
SQL> grant sysdba to eygle; 
grant sysdba to eygle 
* 
ERROR at line 1: 
ORA-01994: GRANT failed: cannot add users to public password file 
SQL> show parameter password 
NAME              TYPE  VALUE 
----------------------------  ------ ------------------------------ 
remote_login_passwordfile   string SHARED

此时的口令文件中是不能添加用户的。很多朋友的疑问在于:口令文件的缺省名称是orapw< ORACLE_SID >,怎么能够共享?

前面已经提到,Oracle数据库在启动时,首先查找的是orapw< ORACLE_SID >的口令文件,如果该文件不存在,则开始查找orapw的口令文件;如果同一主机上的多个数据库同时使用orapw文件,则口令文件就可以共享(当然通过其他方式,如符号链接等也可以实现共享)。

来看一下测试,首先移动缺省的口令文件:

[oracle@jumper dbs] $ mv orapweygle orapweygle.b

此时,启动数据库会出现如下错误:

SQL> startup force; 
ORACLE instance started. 

ORA-01990: error opening password file '/opt/oracle/product/9.2.0/dbs/orapw' 
ORA-27037: unable to obtain file status 
Linux Error: 2: No such file or directory 
Additional information: 3

复制一个orapw口令文件,这时候再启动数据库就不会出现这个错误:

SQL> ! cp orapweygle.b orapw 
SQL> startup force; 
ORACLE instance started. 
Database mounted. 
Database opened.   
SQL> show parameter password 
NAME                 TYPE    VALUE 
------------------------------------ ----------- ------------------------------ 
remote_login_passwordfile      string   SHARED

那么你可能会有这样的疑问:多个Exclusive的数据库是否可以共享一个口令文件(orapw)呢?

继续这个测试,首先查看一下口令文件的内容,注意这里仅记录着INTERNAL/SYS的口令:

[oracle@jumper dbs] $ strings orapw 
]\[Z 
ORACLE Remote Password file 
INTERNAL 
AB27B53EDC5FEF41 
8A8F025737A9097A

当REMOTE_LOGIN_PASSWORDFILE=EXCLUSIVE时:

SQL> alter system set remote_login_passwordfile=exclusive scope=spfile; 
System altered. 
SQL> startup force; 
ORACLE instance started. 
Database mounted. 
Database opened. 
SQL> ! strings orapw 
]\[Z 
ORACLE Remote Password file 
EYGLE 
INTERNAL 
AB27B53EDC5FEF41 
8A8F025737A9097A

注意:

这里以EXCLUSIVE方式启动以后,实例名称信息被写入口令文件。
此时,如果有其他实例以Exclusive模式启动,仍然可以使用这个口令文件,口令文件中的实例名称同时被改写,也就是说,数据库只在启动过程中才读取口令文件,数据库运行过程中并不锁定该文件,类似于pfile/spfile文件。

进一步地,如果对其他用户授予SYSDBA的身份:

SQL> select * from v$pwfile_users; 
USERNAME    SYSDB   SYSOP 
----------------- -------- -------- 
SYS   TRUE   TRUE 
SQL> grant sysdba to eygle; 
Grant succeeded. 
SQL> select * from v$pwfile_users; 
USERNAME   SYSDB  SYSOP 
----------------- ----- ----- 
SYS    TRUE   TRUE 
EYGLE     TRUE  FALSE 
SQL> ! strings orapw 
]\[Z ORACLE Remote Password file 
EYGLE 
INTERNAL 
AB27B53EDC5FEF41 
8A8F025737A9097A 
>EYGLE 
B726E09FE21F8E83

注意此时增加的SYSDBA用户,其相关信息可以被写入到口令文件,一旦口令文件中增加了其他SYSDBA用户,此文件就不再能够被其他Exclusive的实例共享。

1.3.7 脚本的执行

继续来看eygle.sql的内容,接下来的脚本才是创建数据库中最关键的:

@C:\oracle\admin\eygle\scripts\CreateDB.sql 
@C:\oracle\admin\eygle\scripts\CreateDBFiles.sql 
@C:\oracle\admin\eygle\scripts\CreateDBCatalog.sql 
@C:\oracle\admin\eygle\scripts\emRepository.sql 
@C:\oracle\admin\eygle\scripts\postDBCreation.sql

第一个脚本是CreateDB.sql,其主要内容如下:

connect "SYS"/"&&sysPassword" as SYSDBA 
set echo on 
spool C:\oracle\admin\eygle\scripts\CreateDB.log 
startup nomount pfile="C:\oracle\admin\eygle\scripts\init.ora"; 
CREATE DATABASE "eygle" 
MAXINSTANCES 8 MAXLOGHISTORY 1 MAXLOGFILES 16 MAXLOGMEMBERS 3 MAXDATAFILES 100 
DATAFILE SIZE 300M AUTOEXTEND ON NEXT 10240K MAXSIZE UNLIMITED EXTENT MANAGEMENT LOCAL
SYSAUX DATAFILE SIZE 120M AUTOEXTEND ON NEXT 10240K MAXSIZE UNLIMITED 
SMALLFILE DEFAULT TEMPORARY TABLESPACE TEMP TEMPFILE SIZE 20M AUTOEXTEND ON NEXT 640K MAXSIZE UNLIMITED 
SMALLFILE UNDO TABLESPACE "UNDOTBS1" DATAFILE SIZE 200M AUTOEXTEND ON NEXT 5120K MAXSIZE UNLIMITED 
CHARACTER SET ZHS16GBK NATIONAL CHARACTER SET AL16UTF16 
LOGFILE GROUP 1 SIZE 51200K,GROUP 2 SIZE 51200K,GROUP 3 SIZE 51200K 
USER SYS IDENTIFIED BY "&&sysPassword" USER SYSTEM IDENTIFIED BY "&&systemPassword"; 
set linesize 2048; 
column ctl_files NEW_VALUE ctl_files; 
select concat('control_files=''', concat(replace(value, ', ', ''','''), '''')) ctl_files from v$ parameter where name ='control_files'; 
host "echo &ctl_files >>C:\oracle\admin\eygle\scripts\init.ora"; 
spool off

可以看到,这个文件的主要操作步骤如下:

(1)通过SYS连接;

(2)通过配置的参数文件init.ora启动实例;

(3)开始数据库创建;

(4)将数据库生成的控制文件名称追加到参数文件。

注意:

由于选择了OMF管理文件,控制文件的名称在创建数据库之前是未知的,所以创建数据库之后才能得到名称加入参数文件中。

1.3.8 db_name参数和instance_name参数

在启动实例后执行的创建数据库中,第一个语句就是:

CREATE DATABASE "eygle"
这是数据库最重要的开始,其中"eygle"也就是图1-4中定义的数据库名称。

对于Oracle数据库来说,db_name代表数据库的名称,而instance_name代表实例的名称,instance_name通过参数文件即可修改,而db_name则不然。

我们来看一下Oracle对于数据库名称的定义:DB_NAME必须是一个不超过8个字符的文本串。在数据库创建过程中,db_name被记录在数据文件,日志文件和控制文件中。如果数据库实例启动过程中参数文件中的db_name和控制文件中的数据库名称不一致,则数据库不能启动。

通过以上定义可以看到,db_name是最具有稳定意义的参数,在数据文件、日志文件和控制文件中都会记录数据库的名称,这个名称完全可以不同于instance_name。又由于db_name具有存储的稳定性,所以不能简单地随意更改。

以下的测试数据库拥有相同的db_name和instance_name:

[oracle@jumper oracle] $ cd $ORACLE_HOME/dbs 
[oracle@jumper dbs] $ grep name initeygle.ora 
*.db_name='eygle' 
*.instance_name='eygle'

我们创建一个新的pfile为julia这个新的实例使用:

[oracle@jumper oracle] $ cd $ORACLE_HOME/dbs 
[oracle@jumper dbs] $ cp initeygle.ora initjulia.ora

修改这个文件更改instance_name参数:

[oracle@jumper dbs] $ grep name initjulia.ora 
*.db_name='eygle' 
*.instance_name='julia'

然后我们启动实例名称为julia的instance:

[oracle@jumper dbs] $ export ORACLE_SID=julia 
[oracle@jumper dbs] $ sqlplus "/ as sysdba" 
SQL*Plus: Release 9.2.0.4.0 - Production on Tue Jul 25 14:04:15 2006 
Copyright (c) 1982, 2002, Oracle Corporation. All rights reserved. 
Connected to an idle instance. 

SQL> startup mount; 
ORACLE instance started. 
ORA-01102: cannot mount database in EXCLUSIVE mode

注意,此时试图加载数据库时会出现错误,因为当前数据库被另外一个实例(eygle instance)加载。在非并行模式(OPS/RAC)下,一个数据库同时只能被一个实例加载。

此时已经启动了两个数据库实例,从后台进程可以看出:

[oracle@jumper dbs] $ ps -ef|grep ora_pmon 
oracle  27321   1 0 Jul14 ?    00:00:00 ora_pmon_eygle 
oracle  15445   1 0 14:04 ?    00:00:00 ora_pmon_julia

关闭eygle这个数据库实例后,就可以通过实例julia加载并打开db_name=eygle的数据库了:

[oracle@jumper dbs] $ export ORACLE_SID=julia 
[oracle@jumper dbs] $ sqlplus "/ as sysdba" 
SQL*Plus: Release 9.2.0.4.0 - Production on Tue Jul 25 14:05:06 2006 
Copyright (c) 1982, 2002, Oracle Corporation. All rights reserved. 
SQL> alter database mount; 
alter database mount 
* 
ERROR at line 1: 
ORA-01990: error opening password file '/opt/oracle/product/9.2.0/dbs/orapw' 
ORA-27037: unable to obtain file status 
Linux Error: 2: No such file or directory 
Additional information: 3 

SQL> alter database open; 
Database altered. 
SQL> select name from v$datafile; 
NAME 
---------------------------------------------------------------------------- 
/opt/oracle/oradata/eygle/system01.dbf 
/opt/oracle/oradata/eygle/undotbs01.dbf 
/opt/oracle/oradata/eygle/users01.dbf 
/opt/oracle/oradata/eygle/eygle01.dbf

新的实例具有独立的instance_name和db_name参数设置:

SQL> ! ps -ef|grep ora_pmon 
oracle  15445   1 0 14:04 ?    00:00:00 ora_pmon_julia 
SQL> show parameter instance_name 
NAME              TYPE    VALUE 
------------------------------------ ----------- ------------------------------ 
instance_name          string   julia 
SQL> show parameter db_name 
NAME              TYPE    VALUE 
------------------------------------ ----------- ------------------------------ 
db_name             string   eygle

我们再来看一看如果参数文件中的db_name和控制文件中的db_name不一致会出现什么错误。

修改参数文件中的db_name参数:

[oracle@jumper dbs] $ grep name initjulia.ora 
*.db_name='julia' 
*.instance_name='julia'

在启动过程中,我们看到,在mount阶段,数据库会对参数文件和控制文件进行比较,如果两者记录的db_name不一致,则数据库无法启动:

SQL> startup nomount; 
ORACLE instance started. 
SQL> alter database mount; 
alter database mount 
* 
ERROR at line 1: 
ORA-01103: database name 'EYGLE' in controlfile is not 'JULIA'

关于db_name在文件头上的存储,可以通过很多方式来读取,以下通过Oracle 9i中随软件提供的BBED可以最为直观的观察和理解(这一工具在Windows平台上,Oracle 9i之后不再提供):

D:\oracle\9.2.0\bin>bbed 
口令:blockedit 

BBED: Release 2.0.0.0.0 - Limited Production on 星期二 8月 31 22:23:27 2010 
Copyright (c) 1982, 2002, Oracle Corporation. All rights reserved. 

************* !!! For Oracle Internal Use only !!! ************************ 
BBED> set filename 'D:\oracle\oradata\EYGLEE\DATAFILE\O1_MF_SYSTEM_60VQT1WW_.DBF' 
    FILENAME   D:\oracle\oradata\EYGLEE\DATAFILE\O1_MF_SYSTEM_60VQT1WW_.DBF 
BBED> set blocksize 8192 
    BLOCKSIZE  8192 
BBED> set block 2 
    BLOCK#   2

进行了如上设置之后,我们可以检查文件头的结构信息,KCVFH是文件头信息的结构体:

BBED> p kcvfh 
struct kcvfh, 360 bytes           @0 
  struct kcvfhbfh, 20 bytes        @0 
   ub1 type_kcbh             @0    0x0b 
   ub1 frmt_kcbh             @1    0xa2 
   ub1 spare1_kcbh            @2    0x00 
   ub1 spare2_kcbh            @3    0x00 
   ub4 rdba_kcbh             @4    0x00400001 
   ub4 bas_kcbh             @8    0x00000000 
   ub2 wrp_kcbh             @12    0x0000 
   ub1 seq_kcbh             @14    0x01 
   ub1 flg_kcbh             @15    0x04 (KCBHFCKV) 
   ub2 chkval_kcbh            @16    0xa837 
   ub2 spare3_kcbh            @18    0x0000 
  struct kcvfhhdr, 76 bytes        @20 
   ub4 kccfhswv             @20    0x00000000 
   ub4 kccfhcvn             @24    0x0b200000 
   ub4 kccfhdbi             @28    0xea51005a 
   text kccfhdbn[0]           @32   E 
   text kccfhdbn[1]           @33   Y 
   text kccfhdbn[2]           @34   G 
   text kccfhdbn[3]           @35   L 
   text kccfhdbn[4]           @36   E 
   text kccfhdbn[5]           @37   E 
   text kccfhdbn[6]           @38 
   text kccfhdbn[7]           @39 
   ub4 kccfhcsq             @40    0x0000064a 
   ub4 kccfhfsz             @44    0x00015400 
   s_blkz kccfhbsz            @48    0x00

在以上输出中,kccfhdbn就是db_name的保留空间,共保留了8位,也正因为如此,数据库的db_name不能超过8个字符。又因为每个文件头上的实体存储,修改db_name的动作会较为复杂,一个名为NID的小工具可以用来更改数据库名称:

E:\>nid -help 
DBNEWID: Release 11.2.0.2.0 - Production on 星期日 1月 23 19:52:01 2011 
Copyright (c) 1982, 2009, Oracle and/or its affiliates. All rights reserved. 
关键字   说明          (默认值) 
---------------------------------------------------- 
TARGET   用户名/口令       (无) 
DBNAME   新的数据库名       (无) 
LOGFILE   输出日志         (无) 
REVERT   还原失败的更改      否 
SETNAME   仅设置新的数据库名    否 
APPEND   附加至输出日志      否 
HELP    显示这些消息        否

最后总结一下,一个实例(instance_name)可以mount并打开任何数据库(db_name),但是同一时间一个实例只能打开一个数据库;一个数据库(db_name)同一时间可以为任一实例(instance_name)所打开,但是在非RAC情况下,同一时间只能被同一个实例所打开。

1.3.9 sql.bsq文件与数据库创建

在CREATE DATABASE的过程中,Oracle会调用$ORACLE_HOME/rdbms/admin/sql.bsq脚本,用于创建数据字典,这是非常重要的一个脚本,其中存储了数据字典的创建语句及注释说明。当我们对某些数据字典存在兴趣时,可以通过检查这个文件得到更为详细的信息,例如,对于控制数据库启动的bootstrap$表,其创建语句就可以从这个文件中找到:

create table bootstrap$ 
( line#     number not null,            /* statement order id */ 
 obj#     number not null,              /* object number */ 
 sql_text   varchar2("M_VCSZ") not null)          /* statement */ 
 storage (initial 50K)      /* to avoid space management during IOR I */ 
//                      /* "//" required for bootstrap */

提示:

sql.bsq文件值得每个接触Oracle数据的人,认真阅读理解。
sql.bsq文件的位置受到一个隐含的初始化参数(_init_sql_file)的控制:

SQL> @GetParDescrb.sql 
Enter value for par: init_sql 
NAME        VALUE          DESCRIB 
--------------- ------------------  ---------------------------------------------------- 
_init_sql_file ?/rdbms/admin/sql.bsq File containing SQL statements to execute upon database creation

如果在数据库的创建过程中,Oracle无法找到sql.bsq文件,则数据库创建将会出错。可以测试一下移除sql.bsq文件,来看一下数据库创建过程:

SQL> startup nomount; 
ORACLE instance started. 

SQL> @CreateDB.sql 
CREATE DATABASE eygle 
* 
ERROR at line 1: 
ORA-01092: ORACLE instance terminated. Disconnection forced

此时警告日志(alert_< oracle_sid >.log)中会记录如下信息:

Fri Aug 18 15:45:49 2006 
Errors in file /opt/oracle/admin/eygle/udump/eygle_ora_3632.trc: 
ORA-01501: CREATE DATABASE failed 
ORA-01526: error in opening file '?/rdbms/admin/sql.bsq' 
ORA-07391: sftopn: fopen error, unable to open text file. 
Error 1526 happened during db open, shutting down database 
USER: terminating instance due to error 1526

这就是sql.bsq文件在数据库创建过程中的作用。知道了这个内容之后,我们甚至可以通过手工修改sql.bsq文件来更改数据库字典对象参数,从而实现特殊要求数据库的创建或测试自定义库,也可以通过修改_init_sql_file参数来重定位sql.bsq文件的位置(但是通常这些是不建议变更的)。

sql.bsq文件中包含的数据库核心信息非常重要,在很多时候,这个文件可以帮助我们解答很多技术疑惑。

注意:

在Oracle 11g中,sql.bsq文件的内容被分散隔离为多个文件。

1.3.10 数据文件及字典的创建

再来看CreateDBFiles.sql文件:

C:\Oracle\admin\eygle\scripts>type CreateDBFiles.sql 
connect "SYS"/"&&sysPassword" as SYSDBA 
set echo on 
spool C:\oracle\admin\eygle\scripts\CreateDBFiles.log 
CREATE SMALLFILE TABLESPACE "USERS" LOGGING DATAFILE SIZE 5M AUTOEXTEND ON NEXT 1280K MAXSIZE UNLIMITED EXTENT MANAGEMENT LOCAL SEGMENT SPACE MANAGEMENT AUTO; 
ALTER DATABASE DEFAULT TABLESPACE "USERS"; 
spool off

这个文件向数据库中追加了USERS表空间,并将该表空间设置为系统缺省的数据表空间,注意最后一句:

ALTER DATABASE DEFAULT TABLESPACE "USERS";

这是Oracle 10g增加的新特性,在Oracle 10g之前,如果创建用户不指定缺省的数据表空间,那么用户的缺省表空间会被指向系统表空间,增加了数据库缺省数据表空间后,如果不指定,那么创建用户的缺省数据表空间会被指向这里:

SQL> create user julia identified by eygle; 
用户已创建。 
SQL> select username,default_tablespace from dba_users 
 2 where username='JULIA'; 
USERNAME          DEFAULT_TABLESPACE 
------------------------------ ------------------------------ 
JULIA           USERS

作为一个数据库属性,这个信息也可以从字典表props$中查询得到:

SQL> select name,value$ from props$ 
 2 where name='DEFAULT_PERMANENT_TABLESPACE'; 
NAME            VALUE$ 
------------------------------ ------------------ 
DEFAULT_PERMANENT_TABLESPACE  USERS

继续前面的讨论,接下来Oracle通过CreateDBCatalog.sql创建数据字典:

C:\Oracle\admin\eygle\scripts>cat CreateDBCatalog.sql 
connect "SYS"/"&&sysPassword" as SYSDBA 
set echo on 
spool C:\oracle\admin\eygle\scripts\CreateDBCatalog.log 
@C:\oracle\10.2.0\rdbms\admin\catalog.sql; 
@C:\oracle\10.2.0\rdbms\admin\catblock.sql; 
@C:\oracle\10.2.0\rdbms\admin\catproc.sql; 
@C:\oracle\10.2.0\rdbms\admin\catoctk.sql; 
@C:\oracle\10.2.0\rdbms\admin\owminst.plb; 
connect "SYSTEM"/"&&systemPassword" 
@C:\oracle\10.2.0\sqlplus\admin\pupbld.sql; 
connect "SYSTEM"/"&&systemPassword" 
set echo on 
spool C:\oracle\admin\eygle\scripts\sqlPlusHelp.log 
@C:\oracle\10.2.0\sqlplus\admin\help\hlpbld.sql helpus.sql; 
spool off

这个文件依次调用Oracle的字典创建文件等。

emRepository.sql文件是用于创建EM档案库的:

C:\Oracle\admin\eygle\scripts>type emRepository.sql 
connect "SYS"/"&&sysPassword" as SYSDBA 
set echo off 
spool C:\oracle\admin\eygle\scripts\emRepository.log 
@C:\oracle\10.2.0\sysman\admin\emdrep\sql\emreposcre C:\oracle\10.2.0 SYSMAN &&sysmanPassword TEMP ON; 
WHENEVER SQLERROR CONTINUE; 
spool off

最后一个执行的文件是postDBCreation.sql:

C:\Oracle\admin\eygle\scripts>cat postDBCreation.sql 
connect "SYS"/"&&sysPassword" as SYSDBA 
set echo on 
spool C:\oracle\admin\eygle\scripts\postDBCreation.log 
connect "SYS"/"&&sysPassword" as SYSDBA 
set echo on 
create spfile='C:\oracle\10.2.0\database\spfileeygle.ora' 
 FROM pfile='C:\oracle\admin\eygle\scripts\init.ora'; 
shutdown immediate; 
connect "SYS"/"&&sysPassword" as SYSDBA 
startup ; 
alter user SYSMAN identified by "&&sysmanPassword" account unlock; 
alter user DBSNMP identified by "&&dbsnmpPassword" account unlock; 
select 'utl_recomp_begin: ' || to_char(sysdate, 'HH:MI:SS') from dual; 
execute utl_recomp.recomp_serial(); 
select 'utl_recomp_end: ' || to_char(sysdate, 'HH:MI:SS') from dual; 
host C:\oracle\10.2.0\bin\emca.bat -config dbcontrol db -silent -DB_UNIQUE_NAME eygle 
  -PORT 1521 -EM_HOME C:\oracle\10.2.0 -LISTENER LISTENER -SERVICE_NAME eygle 
  -SYS_PWD &&sysPassword -SID eygle -ORACLE_HOME C:\oracle\10.2.0 
  -DBSNMP_PWD &&dbsnmpPassword -HOST gqgai -LISTENER_OH C:\oracle\10.2.0 
  -LOG_FILE C:\oracle\admin\eygle\scripts\emConfig.log -SYSMAN_PWD &&sysmanPassword; 
spool C:\oracle\admin\eygle\scripts\postDBCreation.log 
exit;

在创建过程中,需要经历以下几个步骤后,数据库的创建才算正式完成:

(1)Oracle首先通过参数文件创建了spfile文件;

(2)解锁两个账号;

(3)编译;

(4)配置EM。

相关文章
|
8天前
|
SQL Oracle 关系型数据库
【Oracle】玩转Oracle数据库(一):装上去,飞起来!
【Oracle】玩转Oracle数据库(一):装上去,飞起来!
44 7
|
15天前
|
存储 关系型数据库 MySQL
轻松入门MySQL:数据库设计之范式规范,优化企业管理系统效率(21)
轻松入门MySQL:数据库设计之范式规范,优化企业管理系统效率(21)
|
29天前
|
SQL 缓存 PHP
PHP技术探究:优化数据库查询效率的实用方法
本文将深入探讨PHP中优化数据库查询效率的实用方法,包括索引优化、SQL语句优化以及缓存机制的应用。通过合理的优化策略和技巧,可以显著提升系统性能,提高用户体验,是PHP开发者不容忽视的重要议题。
|
1月前
|
Oracle 关系型数据库 数据库
|
25天前
|
Oracle 关系型数据库 数据库
Oracle数据库基本概念理解(3)
Oracle数据库基本概念理解(3)
18 2
|
7天前
|
SQL Oracle 关系型数据库
【Oracle】玩转Oracle数据库(七):RMAN恢复管理器
【Oracle】玩转Oracle数据库(七):RMAN恢复管理器
35 5
|
15天前
|
存储 关系型数据库 MySQL
MySQL数据库性能大揭秘:表设计优化的高效策略(优化数据类型、增加冗余字段、拆分表以及使用非空约束)
MySQL数据库性能大揭秘:表设计优化的高效策略(优化数据类型、增加冗余字段、拆分表以及使用非空约束)
|
25天前
|
Oracle 关系型数据库 数据库
Oracle数据库基本概念理解(2)
Oracle数据库基本概念理解(2)
13 1
|
3天前
|
SQL 缓存 Java
Java数据库连接池:优化数据库访问性能
【4月更文挑战第16天】本文探讨了Java数据库连接池的重要性和优势,它能减少延迟、提高效率并增强系统的可伸缩性和稳定性。通过选择如Apache DBCP、C3P0或HikariCP等连接池技术,并进行正确配置和集成,开发者可以优化数据库访问性能。此外,批处理、缓存、索引优化和SQL调整也是提升性能的有效手段。掌握数据库连接池的使用是优化Java企业级应用的关键。
|
4天前
|
SQL 关系型数据库 数据库
【后端面经】【数据库与MySQL】SQL优化:如何发现SQL中的问题?
【4月更文挑战第12天】数据库优化涉及硬件升级、操作系统调整、服务器/引擎优化和SQL优化。SQL优化目标是减少磁盘IO和内存/CPU消耗。`EXPLAIN`命令用于检查SQL执行计划,关注`type`、`possible_keys`、`key`、`rows`和`filtered`字段。设计索引时考虑外键、频繁出现在`where`、`order by`和关联查询中的列,以及区分度高的列。大数据表改结构需谨慎,可能需要停机、低峰期变更或新建表。面试中应准备SQL优化案例,如覆盖索引、优化`order by`、`count`和索引提示。优化分页查询时避免大偏移量,可利用上一批的最大ID进行限制。
32 3