熱點推薦:
您现在的位置: 電腦知識網 >> 編程 >> Oracle >> 正文

Oracle數據庫的啟動-nomount狀態深入解析

2022-06-13   來源: Oracle 

  以下是《深入解析Oracle》一書第一章的第一部分內容

  通常所說的Oracle Server主要由兩個部分組成Instance和DatabaseInstance是指一組後台進程(在Windows上是一組線程)和一塊共享內存區域Database是指存儲在磁盤上的一組物理文件通過Instance與Database協同Oracle數據庫才能形成一個動態的可訪問關系型數據庫系統

  本章將由數據庫如何啟動與關閉入手開始和大家一起進入Oracle數據庫的國度效果如下這是一個普遍性問題ig中都存在

   數據庫的啟動

  從表象來看數據庫的啟動極其簡單只需要以SYSDBA/SYSOPER身份登陸敲一條startup命令既可啟動數據庫然而在這條命令之後Oracle需要執行一系列復雜的操作深入理解這些操作不僅有助於了解Oracle數據庫的運行機制還可以在故障發生時幫助大家快速的定位問題的根源所在所以接下來讓我們一起分析一下數據庫的啟動過程

  Oracle數據庫的啟動主要包含三個步驟

  啟動數據庫到Nomount狀態

  啟動數據庫到Mount狀態

  啟動數據庫到Open狀態

  完成這三個過程數據庫才能進入就緒狀態准備提供數據訪問下面逐個來看看以上各個步驟的具體過程以及含義

   啟動數據庫到Nomount狀態

  在啟動的第一步驟Oracle首先尋找參數文件(pfile/spfile)然後根據參數文件中的設置(如內存分配等設置)創建實例(INSTANCE)分配內存啟動後台進程Nomount的過程也就是啟動數據庫實例的過程這個過程在後台是啟動Oracle可執行程序的過程Windows上是oracleexe文件的初始化在Unix/Linux上是oracle可執行文件的初始化

  Windows上Oracleg的執行文件大小約為M而Linux下Oracleg的執行文件達到M左右

  

  D:\oracle\product\\BIN>dir oracleexe
: oracleexe
[oracle@localhost bin]$ ls al $ORACLE_HOME/bin/oracle
rwsrsx oracle dba Jul : /opt/oracle/product//bin/oracle

  在Unix/Linux上可以通過file命令查看oracle執行文件來判斷Oracle是位或是位的以下是Linux平台的一個示范輸出輸出顯示Oracle為

  

  [oracle@localhost bin]$ file $ORACLE_HOME/bin/oracle
/opt/oracle/product//bin/oracle: setuid setgid ELF bit LSB executable Intel version (SYSV) for GNU/Linux dynamically linked (uses shared libs) not stripped

  在Windows上也有可選的命令增強工具可以提供類似的功能

  了解Oracle可執行文件還有另外一個用途在Unix/Linux上通過strings命令可以將oracle可執行文件中的字符文本轉儲出來在轉儲的文本中可以找到很多有意思的信息比如一些Oracle未公開的Hints信息數據庫字典基表創建信息等類似如下一條命令可以完成這樣的工作strings $ORACLE_HOME/bin/oracle > oracletxt在Nomount初始化的過程中只要擁有了一個參數文件就可以憑之啟動實例(INSTANCE)這一步驟並不需要任何控制文件或數據文件等的參與

   實例以及進程的創建

  以下是正常情況下啟動到nomount狀態的過程

  

  [oracle@eygle bdump]$ sqlplus /nolog
SQL*Plus: Release Production on Wed Jun ::
Copyright (c) Oracle All rights reserved
SQL> connect / as sysdba
Connected to an idle instance
SQL> startup nomount;
ORACLE instance started

  Total System Global Area bytes
Fixed Size bytes
Variable Size bytes
Database Buffers bytes
Redo Buffers bytes

  注意這裡Oracle根據參數文件的內容創建了instance分配了相應的內存區域啟動了相應的後台進程SGA的分配信息從以上輸出中可以看到

  觀察告警日志文件(alert_log)可以看到這一階段的啟動過程讀取參數文件應用參數啟動實例所有在參數文件中定義的非缺省參數都會記錄在告警日志文件中以下是這一過程的日志摘要示例

  

  Wed Jun ::
Starting ORACLE instance (normal)
LICENSE_MAX_SESSION =
LICENSE_SESSIONS_WARNING =
Picked latchfree SCN scheme
Autotune of undo retention is turned on
IMODE=BR
ILAT =
LICENSE_MAX_USERS =
SYS auditing is disabled
ksdpec: called for event prior to event group initialization
Starting up ORACLE RDBMS Version:
System parameters with nondefault values:
processes =
__shared_pool_size =
__large_pool_size =
__java_pool_size =
__streams_pool_size =
sga_target =
control_files = /opt/oracle/oradata/eygle/controlctl /opt/oracle/oradata/eygle/controlctl /opt/oracle/oradata/eygle/controlctl
db_block_size =
__db_cache_size =

background_dump_dest = /opt/oracle/admin/eygle/bdump
user_dump_dest = /opt/oracle/admin/eygle/udump
db_name = eygle

  應用參數創建實例之後後台進程依次啟動注意以下輸出中包含了PID信息以及OS ID兩個信息PID代表該進程在數據庫內部的標識符編號而OS ID則代表該進程在操作系統上的進程編號

  

  PMON started with pid= OS id=
PSP started with pid= OS id=
MMAN started with pid= OS id=
DBW started with pid= OS id=
LGWR started with pid= OS id=
CKPT started with pid= OS id=
SMON started with pid= OS id=
RECO started with pid= OS id=
CJQ started with pid= OS id=
MMON started with pid= OS id=
MMNL started with pid= OS id=

  在這裡提醒大家注意一下Oracle不同版本告警日志信息的變化在Oraclei早期版本中後台進程啟動的日志信息裡並不包含OS ID以下是Oracle 的日志信息(在Oracle 中已經包含了OS ID信息)

  

  PMON started with pid=
DBW started with pid=
LGWR started with pid=
CKPT started with pid=
SMON started with pid=
RECO started with pid=

  在Oracle g中這部分信息有了進一步的增強輸出中不僅包含了OS ID而且每個後台進程的啟動都有單獨的時間標記(時間標記可以幫助我們判斷每個後台進程啟動時所消耗的時間從而輔助進行問題診斷)

  

  Sat Jul ::
PMON started with pid= OS id=
Sat Jul ::
VKTM started with pid= OS id= at elevated priority
VKTM running at ()ms precision
Sat Jul ::
DIAG started with pid= OS id=
Sat Jul ::
DBRM started with pid= OS id=
Sat Jul ::
PSP started with pid= OS id=

  提示從Oracle不同版本中的變化來體會Oracle的技術進步甚至借鑒這些變化是學習Oracle的方法之一任何細微的變化都值得注意認真細致嚴謹是對DBA的基本素質要求

  細心的讀者朋友或許可以注意到在前面日志裡的進程啟動信息裡並沒有pid=的進程那麼這個進程是否存在呢?

   V$PROCESS視圖

  通過數據庫中的v$process視圖可以找到對應於操作系統的每個進程信息

  

  SQL> select addrpidspidusernameprogram from v$process;
ADDR PID SPID USERNAME PROGRAM

FEAC PSEUDO
FE oracle oracle@eygle (PMON)
FEE oracle oracle@eygle (PSP)
FEC oracle oracle@eygle (MMAN)
FEC oracle oracle@eygle (DBW)
FEF oracle oracle@eygle (LGWR)
FEE oracle oracle@eygle (CKPT)

  注意以上輸出pid=的進程是一個PSEUDO進程這個進程被認為是初始化數據庫的進程啟動其他進程之前即被占用並在數據庫中一直存在v$process的查詢輸出中SPID列代表的就是操作系統上的進程號通過SPID可以將進程從操作系統到數據庫關聯起來

  

  [oracle@eygle bdump]$ ps ef|grep ora_
oracle : ? :: ora_pmon_eygle
oracle : ? :: ora_psp_eygle
oracle : ? :: ora_mman_eygle
oracle : ? :: ora_dbw_eygle
oracle : ? :: ora_lgwr_eygle
oracle : ? :: ora_ckpt_eygle

  如果在操作系統上發現某個進程表現異常(如占用很高的CPU資源)那麼通過操作系統上的PID和V$PROCESS視圖中的SPID關聯就可以找到這個OS上的進程在數據庫內部的化身從而可以進行進一步的跟蹤診斷

  V$PROCESS視圖包含當前數據庫中活動進程的相關信息這些進程在操作系統上都存在與之對應的OS進程其中LATCHWAIT列代表進程當前正在等待的LATCH信息LATCHSPIN則記錄進程正在通過SPIN進行LATCH的競爭Latch通常被稱為闩是數據庫內部的串行鎖機制主要用來控制內存上的並發在多處理器系統上Oracle進程通過自旋(spin)來進行Latch爭奪

  這個視圖結構如下所示(OraclegR信息)

  

  SQL> desc v$process
Name Null? Type

ADDR RAW()
PID NUMBER
SPID VARCHAR()
USERNAME VARCHAR()
SERIAL# NUMBER
TERMINAL VARCHAR()
PROGRAM VARCHAR()
TRACEID VARCHAR()
BACKGROUND VARCHAR()
LATCHWAIT VARCHAR()
LATCHSPIN VARCHAR()
PGA_USED_MEM NUMBER
PGA_ALLOC_MEM NUMBER
PGA_FREEABLE_MEM NUMBER
PGA_MAX_MEM NUMBER

  注意這裡的ADDR字段代表的是進程的地址進程的狀態等信息在內存中記錄這個ADDR記錄的正是這樣的內存地址信息ADDR在數據庫中(甚至是所有軟件中)是非常重要的雖然通常並不會用到但是深入理解這些知識有助於大家更好的了解Oracle數據庫

  進程的地址(Address of process)進一步的被縮寫為PADDR在V$SESSION視圖中記錄的PADDR就是V$PROCESSADDR的進一步延伸通過兩者關聯可以向數據庫進一步深入

  如果向操作系統端延伸則SPID代表的正是操作系統進程標識符(Operating system process identifier)通過SPID和OS中看到的進程PID關聯就可以建立從操作系統到數據庫的關聯

  所以V$PROCESS被認為是從操作系統到數據庫的入口此外和PGA相關的幾個字段則記錄了進程的PGA使用情況

   參數文件的選擇

  接下來關注一下啟動過程中Oracle選擇參數文件的順序

  從Oraclei開始spfile被引入Oracle數據庫Oracle首選spfile<ORACLE_SID>ora文件作為啟動參數文件如果該文件不存在Oracle選擇spfileora文件如果前兩者都不存在Oracle將會選擇init<ORACLE_SID>ora文件如果以上三個文件都不存在Oracle將無法創建和啟動instanceOracle在啟動過程中會在特定的路徑中尋找參數文件在Unix/Linux下的路徑為$ORACLE_HOME/dbs目錄在WINDOWS上的路徑為$ORACLE_HOME\database目錄

  可以在SQL*PLUS中通過show parameter spfile命令來檢查數據庫是否使用了spfile文件如果value不為Null則數據庫使用了spfile文件

  

  SQL> show parameter spfile
NAME TYPE VALUE

spfile string ?/dbs/spfile@ora

  注意這裡的代表ORACLE_HOME@代表數據庫的sid現在如果更名spfile<ORACLE_SID>ora文件此後Oracle將選擇spfileora文件啟動數據庫

  

  [oracle@jumper dbs]$ mv spfileconnerora spfileconnerorabak
SQL> startup nomount
SQL> show parameter spfile
NAME TYPE VALUE

spfile string ?/dbs/spfileora

  進一步的如果再更名spfileora文件此後Oracle將選擇initora文件啟動數據庫

  

  [oracle@jumper dbs]$ mv spfileora spfileorabak
SQL> startup nomount
SQL> show parameter spfile
NAME TYPE VALUE

spfile string

  如果這三個文件都不存在Oracle將無法啟動

  

  [oracle@jumper dbs]$ mv initconnerora initconnerorabak
SQL> startup
ORA: failure in processing system parameters
LRM: could not open parameter file /opt/oracle/product//dbs/initconnerora

  注意這裡出現的錯誤提示報告無法找到參數文件init<ORACLE_SID>ora這正是Oracle在啟動過程中最後一個查找的參數文件

  在Oracle整個啟動過程中參數文件是寫在應用程序中的硬代碼按照前面描述的順序進行查找以下是來自源碼中關於參數文件及其查找順序的定義

  ?/dbs/spfile@ora

  ?/dbs/spfileora

  ?/dbs/init@ora

  雖然不能改變Oracle對於參數文件的搜索路徑及行為但是如果參數文件不在相應的位置在Linux/Unix系統上可以通過符號鏈接來進行重定位以滿足一些特殊需要(具體請參考第三章內容)

   實例啟動最小參數需求

  在參數文件中通常需要最少的參數是db_name 設置了這個參數之後數據庫實例就可以啟動來看一個簡單的測試

  可以隨意命名一個ORACLE_SID(測試來自於Linux下適用於Linux/Unix對於Windows平台需要通過oradimexe工具創建服務)然後嘗試啟動到nomount狀態

  

  [oracle@jumper dbs]$ export ORACLE_SID=julia
[oracle@jumper dbs]$ sqlplus / as sysdba
SQL*Plus: Release Production on Mon May ::
Copyright (c) Oracle Corporation All rights reserved
Connected to an idle instance

  SQL> startup nomount;
ORA: failure in processing system parameters
LRM: could not open parameter file /opt/oracle/product//dbs/initjuliaora

  參數文件查找失敗會給出提示信息此時創建一個最簡單的參數文件(僅包含DB_NAME初始化參數)然後就可以啟動實例

  

  SQL> ! echo db_name=julia > /opt/oracle/product//dbs/initjuliaora
SQL> startup nomount;
ORACLE instance started

  Total System Global Area bytes
Fixed Size bytes
Variable Size bytes
Database Buffers bytes
Redo Buffers bytes

  缺省的如果不設置background_dump_dest目錄(告警日志文件alert_<ORACLE_SID>log的存放地點)位於$ORACLE_HOME/rdbms/log目錄下

  

  SQL> show parameter background_dump
NAME TYPE VALUE

background_dump_dest string ?/rdbms/log

  順便看下其他幾個缺省路徑的地點

  

  SQL> show parameter dump_dest
NAME TYPE VALUE

background_dump_dest string ?/rdbms/log
core_dump_dest string ?/dbs
user_dump_dest string ?/rdbms/log
SQL> show parameter control_files
NAME TYPE VALUE

control_files string ?/dbs/cntrl@dbf

  收錄簡單啟動實例日志供大家參考

  

  [oracle@jumper dbs]$ cat $ORACLE_HOME/rdbms/log/alert_julialog
Mon May ::
Starting ORACLE instance (normal)
Mon May ::
LICENSE_MAX_SESSION =
LICENSE_SESSIONS_WARNING =
SCN scheme
Using log_archive_dest parameter default value
LICENSE_MAX_USERS =
SYS auditing is disabled
Starting up ORACLE RDBMS Version:
System parameters with nondefault values:
db_name = julia
PMON started with pid=
DBW started with pid=
LGWR started with pid=
CKPT started with pid=
SMON started with pid=
RECO started with pid=

  這樣通過以上步驟就以最少的參數需求啟動了Oracle實例

   ORACLE_SID的含義

  回顧一下前面的內容可以注意到SID和ORACLE_SID已經多次出現那麼SID是什麼?在數據庫啟動過程中又起到什麼作用呢?

  SID是System IDentifier的縮寫而ORACLE_SID就是Oracle System IDentifier 的縮寫在Oracle系統中ORACLE_SID以環境變量的形式出現當Oracle實例啟動時在操作系統上fork的進程就依據這個ORACLE_SID來創建這就是SID的作用

  Oracle的實例(instance)是由一塊共享內存區域(SGA)和一組後台進程(background processes)共同組成而後台進程正是數據庫和操作系統進行交互的通道這些進程的名稱就是通過ORACLE_SID決定的

  通過前面的討論可以知道實例的啟動需要一個參數文件參數文件的名稱就是由ORACLE_SID決定的對於init文件缺省的文件名稱是init<ORACLE_SID>ora對於spfile文件缺省的文件名為spfile<ORACLE_SID>oraOracle依據ORACLE_SID來決定和尋找參數文件啟動實例

  在同一個$ORACLE_HOME下通過參數文件Oracle能夠根據ORACLE_SID將實例區分開來但是注意如果在不同的$ORACLE_HOME下即使在同一台主機上Oracle也是能夠創建相同ORACLE_SID的實例的

  以下一個測試首先啟動一個Oraclei下ORACLE_SID為eygle的實例

  

  $ export ORACLE_SID=eygle
$ sqlplus / as sysdba
SQL*Plus: Release Production on Fri Feb ::
(c) Copyright Oracle Corporation All rights reserved
Connected to an idle instance

  SQL> startup nomount;
ORACLE instance started
SQL> ! ps ef|grep ora_smon_eygle
oracle :: pts/ : grep ora_smon_eygle
oracle :: ? : ora_smon_eygle

  接下來又可以啟動另外$ORACLE_HOME下ORACLE_SID為eygle的實例

  

  $ export ORACLE_SID=eygle
$ sqlplus / as sysdba
SQL*Plus: Release Production on Fri Feb ::
Copyright (c) Oracle Corporation All rights reserved
Connected to an idle instance

  SQL> startup nomount;
ORACLE instance started
SQL> ! ps ef|grep ora_smon_eygle
oracle :: pts/ : grep ora_smon_eygle
oracle :: ? : ora_smon_eygle
oracle :: ? : ora_smon_eygle

  現在這同一台主機上就啟動了兩個相同名稱的實例在操作系統上Oracle能夠通過ID標示將共享內存或信號量區分開來

  

  $ ipcs i
IPC status from as of Fri Feb :: CST
T ID KEY MODE OWNER GROUP
Message Queues:
q xed rwrr root root
T ID KEY MODE OWNER GROUP ISMATTCH
Shared Memory:
m xabdcb rwr oracle dba
m x rwr oracle dba
Semaphores:
s xbac rar oracle dba
s xaef rar oracle dba

  通過Oracle提供的一個小工具sysresv我們可以找到對應於不同的ORACLE_SID操作系統上創建的共享內存段ID(Shared Memory)和信號量ID(Semaphores)等信息:

  

  $ sysresv l eygle julia
IPC Resources for ORACLE_SID eygle :
Shared Memory:
ID KEY
x
Semaphores:
ID KEY
xaef
Oracle Instance alive for sid eygle
IPC Resources for ORACLE_SID julia :
Shared Memory:
ID KEY
xab
Semaphores:
ID KEY
xaa
Oracle Instance alive for sid julia

   INSTANCE_NAME的含義

  在數據庫內部和ORACLE_SID相關聯的概念就是INSTANCE_NAME Oracle數據庫內部存在一個初始化參數INSTANCE_NAME用於標示數據庫實例的名稱其缺省值通常就是ORACLE_SID但是初始化參數INSTANCE_NAME和ORACLE_SID可以不同不同實例可以擁有相同的INSTANCE_NAME在同一個ORACLE_HOME下只要ORACLE_SID不同數據庫並不校驗INSTANCE_NAME參數通過簡單的參數文件復制我們就可以在同一台服務器上創建多個具有相同instance_name的實例(注意以下測試來自Oraclei數據庫)

  

  bash$ cd $ORACLE_HOME/dbs
bash$ cp initeygleora initjuliaora
bash$ export ORACLE_SID=julia
bash$ sqlplus / as sysdba
SQL> startup nomount;
ORACLE instance started

  Total System Global Area bytes
Fixed Size bytes
Variable Size bytes
Database Buffers bytes
Redo Buffers bytes

  此時同一主機上就可以啟動多個實例ORACLE_SID不同但是擁有了相同的instance_name

  

  SQL> show parameter instance_name
NAME TYPE VALUE

instance_name string eygle

  但是注意在數據庫內部視圖V$INSTANCE中也記錄著一個INSTANCE_NAME這個INSTANCE_NAME來自數據庫實例的SID始終和ORACLE_SID保持一致這就可能出現數據庫中這兩個INSTANCE_NAME不一致的情況

  

  SQL> select instance_name from v$instance;
INSTANCE_NAME

julia
SQL> show parameter instance_name
NAME TYPE VALUE

instance_name string eygle

  所以存在這種歧義是因為在Oraclei中當創建數據庫進行相關配置時數據庫將INSTANCE_NAME參數寫入了參數文件這就導致了當我們修改參數文件名稱變更ORACLE_SID時可能並不修改INSTANCE_NAME參數的情況值得注意的是從Oracleg開始參數文件中缺省不再記錄INSTANCE_NAME此時INSTANCE_NAME可以動態從系統獲得從而消除了以前可能常見的歧義

  

  D:\oracle\product>grep instance_name \database\SPFILEEEYGLEORA
*instance_name=eeygle
D:\oracle\product>grep instance_name \database\SPFILEEYGLEORA
D:\oracle\product>grep instance_name \database\SPFILEEYGLEEORA

  INSTANCE_NAME除了用來標識實例名稱之外在監聽器動態注冊時還會用於向監聽器注冊比如在一個數據庫db_name=juliainstance_name=eygle的數據庫中監聽器動態注冊會包含如下信息這裡的Instance內容就來自INSTANCE_NAME參數設置

  

  Services Summary
Service julia has instance(s)
Instance eygle status READY has handler(s) for this service

  V$INSTANCE視圖和數據庫實例的生命周期相關用於顯示當前實例的狀態通過這個視圖可以獲得包括實例的啟動時間運行主機等重要信息通過以下一段SQL可以獲得數據庫的UPTIME信息

  

  SQL> COLUMN STARTED_AT format a
SQL> COLUMN UPTIME format a
SQL> SELECT TO_CHAR (startup_time DDMONYYYY HH:MI:SS) started_at
TRUNC (SYSDATE (startup_time))
|| day(s) || TRUNC ( * ((SYSDATE startup_time)
TRUNC (SYSDATE startup_time)))
|| hour(s) || MOD (TRUNC ( * ( (SYSDATE startup_time)
TRUNC (SYSDATE startup_time))))
|| minute(s) || MOD (TRUNC ( * ( (SYSDATE startup_time)
TRUNC (SYSDATE startup_time))))
|| seconds uptime
FROM v$instance;
STARTED_AT UPTIME

JUL :: day(s) hour(s) minute(s) seconds

   DB_NAME與INSTANCE_NAME

  相較INSTANCE_NAME參數來說對於Oracle數據庫更為重要的一個參數是DB_NAMEDB_NAME代表了實例即將掛接的數據庫名稱關系到具體的物理文件通常缺省的數據庫instance_name和db_name可以設置相同(在RAC環境下由於多個實例對應一個數據庫所以instance_name和db_name不同)

  在創建數據庫的過程中下圖是用於定義數據庫名稱(db_name)和影響INSTANCE_NAME的SID

  Oracle文檔中對於db_name的定義如下DB_NAME用來定義數據庫名稱必須是一個不超過個字符的文本串在數據庫創建過程中db_name被記錄在數據文件日志文件和控制文件中如果數據庫實例啟動過程中參數文件中的db_name和控制文件中的數據庫名稱不一致則數據庫不能啟動

  此外常見的幾個結論有

   一個實例可以mount並打開任何數據庫但是同一時間一個實例只能打開一個數據庫

   一個數據庫可以被一個或多個實例所mount並打開(在OPS/RAC環境下一個數據庫可以被多個實例所打開)

  DB_NAME的另外一個作用是在監聽器動態注冊時作為缺省服務名注冊以下是Oracleg的動態注冊監聽示范

  

  Services Summary
Service julia has instance(s)
Instance eygle status READY has handler(s) for this service

  通過下面的測試來看一下DB_NAME與數據庫的關系首先initeygleora文件代表了一個數據庫實例

  

  [oracle@jumper oracle]$ cd $ORACLE_HOME/dbs
[oracle@jumper dbs]$ grep name initeygleora
*db_name=eygle
*instance_name=eygle

  這個實例以及當前數據庫的相關參數如下

  

  SQL> show parameter db_name
NAME TYPE VALUE

db_name string eygle
SQL> show parameter instance_name
NAME TYPE VALUE

instance_name string eygle

  現在創建另外一個實例通過復制創建一個pfile文件為名為julia這個新的實例使用

  

  [oracle@jumper oracle]$ cd $ORACLE_HOME/dbs
[oracle@jumper dbs]$ cp initeygleora initjuliaora
[oracle@jumper dbs]$ ll init*
rwrr oracle dba Jul : initeygleora
rwrr oracle dba Jul : initjuliaora

  修改這個文件更改instance_name參數設置instance_name = julia修改後的參數設置如下所示:

  

  [oracle@jumper dbs]$ grep name initjuliaora
*db_name=eygle
*instance_name=julia

  現在來啟動這個實例名稱為julia的instance

  

  [oracle@jumper dbs]$ export ORACLE_SID=julia
[oracle@jumper dbs]$ sqlplus / as sysdba
SQL> startup mount;
ORACLE instance started

  Total System Global Area bytes
Fixed Size bytes
Variable Size bytes
Database Buffers bytes
Redo Buffers bytes
ORA: cannot mount database in EXCLUSIVE mode

  注意當試圖加載數據庫時出現錯誤因為當前數據庫被另外一個實例(instance)加載在非並行模式(Ops/RAC)下一個數據庫同時只能被一個實例加載

  此時已經啟動了兩個數據庫實例從後台進程可以看出

  

  [oracle@jumper dbs]$ ps ef|grep dbw
oracle Jul ? :: ora_dbw_eygle
oracle : ? :: ora_dbw_julia
oracle : pts/ :: grep dbw

  關閉eygle這個數據庫實例:

  

  [oracle@jumper dbs]$ export ORACLE_SID=eygle
[oracle@jumper dbs]$ sqlplus / as sysdba
SQL> shutdown immediate;

  然後就可以通過實例julia加載並打開db_name=eygle的數據庫了這也就是前面所說的一個數據庫可以被任何一個實例掛接打開(當然是有條件限制的)

  

  [oracle@jumper dbs]$ export ORACLE_SID=julia
[oracle@jumper dbs]$ sqlplus / as sysdba
SQL> alter database mount;
alter database mount
*
ERROR at line :
ORA: error opening password file /opt/oracle/product//dbs/orapw
ORA: unable to obtain file status
Linux Error: : No such file or directory
Additional information:
SQL> alter database open;
Database altered
SQL> select name from v$datafile;
NAME

/opt/oracle/oradata/eygle/systemdbf
/opt/oracle/oradata/eygle/undotbsdbf
/opt/oracle/oradata/eygle/usersdbf
/opt/oracle/oradata/eygle/eygledbf
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 initjuliaora
*db_name=julia
*instance_name=julia

  在nomount環節不存在任何問題而在mount階段數據庫會對參數文件和控制文件進行比較如果兩者記錄的db_name不一致則數據庫無法啟動錯誤提示指定的數據庫名稱和控制文件中記錄的名稱不符

  

  SQL> startup nomount;
SQL> alter database mount;
alter database mount
*
ERROR at line :
ORA: database name EYGLE in controlfile is not JULIA

   RMAN的缺省實例

  在使用RMAN(Recovery Manager)時存在更為特殊的情況Oracle允許在不存在參數文件的情況下啟動一個實例數據庫的db_name會被缺省的命名為DUMMY這是最為極端的情況在某些恢復過程中這個功能可以幫助我們減少很多麻煩

  

  [oracle@jumper dbs]$ rman target /
Recovery Manager: Release Production
Copyright (c) Oracle Corporation All rights reserved
connected to target database (not started)
RMAN> startup nomount;
startup failed: ORA: failure in processing system parameters
LRM: could not open parameter file /opt/oracle/product//dbs/initconnerora
trying to start the Oracle instance without parameter files
Oracle instance started
Total System Global Area bytes
Fixed Size bytes
Variable Size bytes
Database Buffers bytes
Redo Buffers bytes

  RMAN> host ;
[oracle@jumper dbs]$ sqlplus / as sysdba
SQL*Plus: Release Production on Tue Mar ::
Copyright (c) Oracle Corporation All rights reserved
SQL> show parameter db_name
NAME TYPE VALUE

db_name string DUMMY

  此時警告日志文件中會記錄如下信息

  

  Starting up ORACLE RDBMS Version:
System parameters with nondefault values:
remote_login_passwordfile= EXCLUSIVE
db_name = DUMMY
PMON started with pid=
DBW started with pid=

  總結一下數據庫的Nomount過程實質上就是在創建實例這個步驟只和參數文件相關在完成實例的創建之後Oracle就可以逐步導航完成數據庫的加載打開等工作

   Nomount案例兩則

  在創建數據庫時如果在這一步驟就出現問題那麼通常可能是系統配置(如內核參數等)存在問題你需要檢查是否分配了足夠的系統資源等

  以下是一個啟動到nomount狀態可能會遇到的常見錯誤

  

  $ export ORACLE_SID=julia
$ sqlplus / as sysdba
SQL*Plus: Release Production on Wed Feb ::
Copyright (c) Oracle Corporation All rights reserved

  Connected to an idle instance

  SQL> startup nomount;
ORA: internal error code arguments: [OSDEP_INTERNAL] [] [] [] [] [] [] []
ORA: failure occurred at: skgpwreset
ORA: additional information: invalid shared ctx
ORA: post/wait initialization failed
ORA: OS system dependent operation:semget failed with status:
ORA: OS failure message: No space left on device
ORA: failure occurred at: sskgpsemsper

  (注意ORA是Oracle內部錯誤的一個集合其具體含義要看後面的參數提示數據庫出現ORA錯誤應當引起DBA的充分重視很多錯誤可能會導致數據損失

  在Nomount狀態就出現問題通常是系統問題OS類錯誤一般說明是系統資源不足這在Linux/Unix下和信號量等參數設置有關多出現在同一主機運行多個數據庫實例的情況(在Solaris上需要修改/etc/system文件中的內核參數重起系統後修改生效)在這個錯誤提示中錯誤的第一個參數是OSDEP_INTERNAL我們大致可以猜測到這是一個OS Dependent/Internal Error很多Oracle的提示可以根據縮寫猜到大致的含義但是如果是錯誤號那就要依賴Oracle的文檔來尋找答案

  在另外一個客戶現場遭遇過另外一個案例當時客戶的服務器異常斷電當系統重新啟動後數據庫無法啟動(提示重啟主機對於DBA來說應當極其慎重很多隱藏的故障可能在重啟時爆發出來在沒有做好充分 之前不要貿然從事)

  數據庫的症狀是啟動主機到Nomount狀態後後台進程會立即將實例中止也就是說數據庫實例都無法穩定創建告警日志文件信息如下

  

  Mon Dec ::
Errors in file /oraclehx/app/admin/sxlss/bdump/sxlss_pmon_trc:
ORA: exception encountered: core dump [] [] [] [] [] []
PSP started with pid= OS id=
MMAN started with pid= OS id=
DBW started with pid= OS id=

SMON started with pid= OS id=
RECO started with pid= OS id=
CJQ started with pid= OS id=
MMON started with pid= OS id=
MMNL started with pid= OS id=
Mon Dec ::
PSP: terminating instance due to error
Instance terminated by PSP pid =

  綜合前面介紹的知識如果實例都無法創建那通常是在OS方面存在問題這些問題在系統重新啟動後才體現出來經過檢查發現客戶系統是AIX操作系統補丁應用不完全最後導致了數據庫無法啟動應用完整的系統補丁後數據庫恢復正常

  

  instfix i|grep ML
All filesets for _AIX_ML were found
All filesets for _AIX_ML were found
All filesets for _AIX_ML were found
All filesets for _AIX_ML were found
All filesets for _AIX_ML were found
All filesets for _AIX_ML were found
Not all filesets for _AIX_ML were found

  這個案例給我們的經驗是當進行OS補丁應用時一定要認真確認對關鍵補丁應當進行服務器重啟驗證不能掉以輕心


From:http://tw.wingwit.com/Article/program/Oracle/201311/17323.html
  • 上一篇文章:

  • 下一篇文章:
  • 推薦文章
    Copyright © 2005-2022 電腦知識網 Computer Knowledge   All rights reserved.