【一】對ORACLE_SID的理解 Oracle中SID的作用類似于一個“開關變量”---引導Oracle在實例啟動時如何去默認位置下讀取適當的參數文件并加載,以正確啟動實例。 我們知道實例的啟動需要指定pfile/spfile(Oracle9i之前是使用pfile--即init文件,從9i開始就默認使用spfile--即服務器端參數文件,兩者的不同請參考《Oracle 10g Concept》手冊,關鍵在于修改其中參數后是否會自動持久化)。這兩個文件的存放位置為: A.pfile:名字為init<ORACLE_SID>.ora B.spfile:名字為spfile<ORACLE_SID>.ora 我們看到init文件和spfile文件都帶有ORACLE_SID的標識,這就是SID的作用了: 【1】當我們要啟動一個實例時,我們首先通過:set ORACLE_SID = XXX 或者export ORACLE_SID = XXX 的方式告訴Oracle接下來要啟動的實例 【2】當我們執行startup nomount時,由于已經指定了SID,那么Oracle知道了如何去默認的目錄下查找該實例對應的參數文件--就是靠SID去匹配每個init/spfile文件 【3】當Oracle找到該文件后(init/spfile),就會讀取該文件的內容,將一系列參數用于分配內存空間,構建后臺進程等實例的啟動過程 【4】當這個實例成功啟動后,我們又可以重新執行 set ORACLE_SID = XXX 或 export ORACLE_SID = XXX 命令再次將“開關撥向”另一個SID,然后重復以上步驟 從上面的過程我們看到Oracle SID的作用是一個明顯的“開關變量”,它拔向那一邊,那么Oracle就會去找和它對應的參數文件來啟動實例。其次SID也起到進程隔離的作用--即SID會在實例的一系列后臺進程中得到體現,如ora_dbw0_paullin,ora_dbw0_boblin。通過SID來命名后臺進程。 操作系統也必須通過SID來和Oracle實例打交道,操作系統并不知道什么INSTANCE_NAME,只知道ORACLE_SID,在Oracle內部由Oracle自己根據這個SID去識別不同的實例。所以ORACLE_SID更多的是“Oracle和外部操作系統溝通的一個窗口”。 【二】對INSTANCE_NAME的理解 相比于ORACLE_SID這樣的“開關變量”,INSTANCE_NAME則是一個實實在在的參數。它是在init/pfile文件中配置的(db_name)。用于標識數據庫實例的名稱,其缺省值就是ORACLE_SID。 INSTANCE_NAME就像一個人的名稱一樣,而SID則是這個人的身份證號碼。通過SID我們找到對應的init/spfile文件,而init/spfile文件中又通過instance_name這個參數告訴我們對應的實例叫什么名字。這樣就把ORACLE_SID、參數文件、INSTANCE_NAME聯系起來了。 造成ORACLE_SID不同,但INSTANCE_NAME相同的原因通常是因為復制了原有的參數文件,但忘記了修改其中的INSTANCE_NAME參數的值。不過在10G之后INSTANCE_NAME這個參數以及從init/spfile中消失了,以免引起混亂。 【三】對DB_NAME的理解 我們已經知道了ORACLE_SID是一個“開關變量”,INSTANCE_NAME是用來描述實例的。那么DB_NAME則是描述實例掛載的數據庫名稱,通過這個DB_NAME我們可以知道對應的磁盤上的控制文件、日志文件、數據文件的位置。 DB_NAME在創建數據庫時被指定,默認情況下和ORACLE_SID的名字一樣。但和INSTANCE_NAME一樣。DB_NAME一旦被確定下來就不能修改了,因為它會同時存儲在init/spfie,控制文件,日志文件,數據文件。你只能修改init/spfile文件中DB_NAME參數的值,但是不能手工修改其它文件的值。所以一旦修改后引起幾個文件的值不匹配那么數據庫的啟動就會失敗。 A.一個實例可以MOUNT并打開任何數據庫(通過init/spfile中配置DB_NAME參數),但是同一時間一個實例只能打開一個數據庫。 B.一個數據庫可以被一個或多個實例所MOUNT并打開(只能是在RAC環境下,普通環境下一個數據庫只能同時被一個實例MOUNT并打開)。 那么如何知道實例應該掛載到那個數據庫并打開呢?就是靠init/spfile中的“control_files”參數來告訴Oracle去那里讀取控制文件,而控制文件中又記錄了數據文件的位置。所以最終形成一個完整的鏈條: ORACLE_SID --> init/spfile文件 --> instance_name、db_name、control_files --> 實例名、數據庫名、控制文件 --> 數據文件 --> 完成掛載并打開 【四】ORACLE_SID、INSTANCE_NAME、DB_NAME對應關系 我們已經知道ORACLE_SID是用來隔離同一個ORACLE_HOME下不同的實例的。但對于不同的ORACLE_HOME呢?能否有相同名稱的SID呢? 實際上這就和文件系統的規則是一樣的:在同一個目錄下不允許有同名的文件存在,但不同的目錄下可以有同名的文件。同樣的在同一個ORACLE_HOME下不能有相同的SID存在,而不同的ORACLE_HOME下可以有重名的SID(即便是同一臺機,只要ORACLE_HOME不同就可以)。 那么對于INSTANCE_NAME呢?默認情況下INSTANCE_NAME和ORACLE_SID是相同的,也可以是不同的;而且不同的實例可以具有相同的實例名。這聽起來有點混亂是不?其實我們可以用一個簡單的生活化例子來解析: 在一個班級Class_1里面,有兩個學生,他們的名稱都叫張三,但他們的學號肯定不同。在這里“張三”就是INSTANCE_NAME,而學號就是SID。所以INSTANCE_NAME重復沒關系,只要SID不同就可以區分開來。 但是在另外一個班級Class_2里面,也有學號相同的學生,這時候就出現了我們說的SID相同的問題,那么如何區分呢?別忘了我們還有班級這個概念啊!對應于ORACLE就是ORACLE_HOME了。 至于INSTANCE_NAME和DB_NAME的對應關系,這個很好理解了,不同的實例可以掛載到不同的DB,也可以掛載到相同的DB嘛。可以把這理解為“多個進程同時對同一份磁盤文件的競爭性訪問”。 A. 相同ORACLE_HOME下,INSTANCE_NAME可以相同,但ORACLE_SID必須唯一。通過ORACLE_SID來區分不同的實例 B. 不同ORACLE_HOME下,ORACLE_SID可以相同,通過ORACLE_HOME來區分不同的SID C.不同INSTANCE_NAME可以對應不同的DB_NAME,也可以對應相同的DB_NAME。但是如果不是在RAC環境下,只能同時啟動實例而不能同時掛載 【五】Oracle實例啟動過程的相關參數文件 前面說到Oracle實例啟動時,需要指定pfile/spfile參數,對應的就是init文件和spfile文件。那么當這兩個文件同時存在時Oracle如何決定讀取那個呢? 以Oracle 9i為例,由于默認采用了spfile來啟動實例,所以查找的順序是: spfile<ORACLE_SID>.ora ---> spfile.ora ---> init<ORACLE_SID>.ora 即默認加載和SID對應的參數文件,如果找不到則采用默認的參數文件,再找不到就用舊的init文件,如果還是找不到則實例無法啟動。下面我們來看看這些文件的內容(以Oracle 10g為例) A.spfile<ORACLE_SID>.ora:
B.init<ORACLE_SID>.ora
我們看到spfile<ORACLE_SID>.ora文件的內容就是我們創建數據庫時在DBCA中填寫的參數,而init<ORACLE_SID>.ora文件的內容則指向了該spfile,所以不論如何都是從spfile來啟動實例了。