shell Ubuntu Python linux 开源 php centos apache 微软 Android google Firefox Windows 云计算 程序员 mysql 编程 java nginx wordpress

《循序漸進Oracle:數據庫管理、優化與備份恢復》一一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。

延伸阅读

评论