關於oracle 12c多租戶可插拔資料庫的啟停分析(一)

darren__chan發表於2017-03-13

       在 Oracle Database 12c中多租戶架構模式 無疑是所有新特性中最大的賣點,在多租戶模式中 把一個單一的多租戶容器資料庫(CDB:Cantainer Database)掛載很多的可插拔資料庫(PDB:P luggable Database )使用,對PDB的不瞭解,也給日常的工作造成了許多的困擾。

一、關閉PDB時遇到的尷尬     

     在最近接觸較多的12c 多租戶資料庫中,有時在當我在CDB中執行“ alter pluggable database xxx close”關閉 某個pdb時,一直無法停止下,會話也hang住,由於當時還未上線,在對pdb不熟悉的情況下,只能直接在CDB下進行shutdown abort了。

     在多租戶的模式下,這實際是不可取的, 整個CDB都shutdown abort 意味著所有的pdb都要同時關閉, 在12.1中多租戶 可以包含252個PDB,而12.2裡可以包含4096個PDB 。在生產環境中,這是災難性的措施,而實際上這是源於對pdb的不瞭解導致。

     以下是在關閉pdb時遇到的過程,透過hanganalyze 我發現停止的過程一直在等待opishd。

      後來我將阻塞的資訊提給了SR,而SR認為這與bug有關: Bug 20528052 - Many AQ$_PLSQL_NTFN jobs executed affecting database performance。實際上對12.1版本存在各種bug,我認為見怪不怪。

     而對於PDB的關閉,其實可以不必透過shutdown abort 整個cdb來實現,但在當時我嘗試 在pdb 裡shutdown abort也貌似停不下來,在12.1.0.1版本資料庫是不允許單個pdb shutdown abort 的,而 在12.1.0.2裡,引進了一個隱含引數 _enable_pdb_close_abort 來設定允許pdb abort,這個引數預設為false,建議將其設定為true開啟,以防關閉pdb時再遇到尷尬。

   在遭遇以上的問題之後,針對pdb的啟停追蹤分析很有必要, 瞭解一個新的事物,首先比較好的方式是瞭解其建立的過程,以下進一步分析PDB的啟動過程,來加深認識多租戶下的pdb。

二、PDB的啟動過程進行分析

首先描述下PDB啟動幾個主要階段:

a.pdb以mount狀態掛載在資料庫例項中

b. PDB_SPFILE$中讀取相關引數

c. container$中更新PDB的狀態資訊

d.透過 建立 bootstrap$引導並載入資料,建立資料庫基表。
e.載入其他資料庫資訊

f.完成啟動

1、PDB的初始狀態

在oracle CDB open 的狀態下,自建pdb預設是以mount狀態掛載在資料庫中,而 PDB$SEED是種子PDB,以read only狀態存在

2、使用10046 追蹤啟動過程:

透過   10046   事件可以跟蹤一下pdb的open過程, 跟蹤檔案裡將記錄從  mount  到  open  的過程中,  Oracle  所執行的後臺操作。


3、資料庫開始解析執行open pdb的語句:

4、從 PDB_SPFILE$中讀取相關引數:

而接下來的第二條語句很明顯是從obj$表中查詢關於PDB_SPFILE$的相關資訊:

     而代入3個變數值可以的 PDB_SPFILE$的物件id為179。

     在之後查詢的語句都是和 PDB_SPFILE$這個物件有關:

    12c pdb 在啟動時便首先讀取PDB_SPFILE$ , PDB_SPFILE$  的作用是什麼呢?

    實際上在ORACLE 12C中引數檔案只是記錄了cdb的引數資訊,並沒有記錄任何的pdb的資訊,在多租戶環境中,每個pdb的引數不一定都相同,因此引入 PDB_SPFILE$來實現pdb引數管理的, p db中引數是記錄在root的PDB_SPFILE$基表中,而 整個CDB的工作原理是如果在PDB_SPFILE$中無相關引數記錄,則繼承cdb的引數檔案中值,如果PDB_SPFILE$中有記錄則使用該值覆蓋cdb引數檔案值。

    12c pdb 在啟動時便首先遍歷PDB_SPFILE$,這也啟動一個資料庫例項時首先讀取引數檔案不盡相同。


5、在 container$中更新PDB的狀態資訊:

接下來對container$表中con_id等於3的記錄進行更新。con_id為3對應的是啟動的pdb2。

      container$表記錄每個pdb的相關資訊, 其中obj#=91978 指的是pdb相應物件號,在oracle 12c 多租戶中,所建立的每個pdb 實際上也同樣以物件的形式儲存在CDB中。

除此之外, container$表也記錄了pdb的dbid,而每個pdb都有自己的dbid來區別,其中。

      同時從create_scnwrp , create_scnbas , clnscnwrp  clnscnbas  可以看出 container$表 還有記錄pdb的SCN相關資訊等。


6、在記憶體中建立 bootstrap$並載入資料進行啟動:

接下來便是建立 bootstrap$表, bootstrap$表是pdb啟動的引導表。

     在這一步驟中,實際上  Oracle  是在記憶體中建立  bootstrap$ 的結構, 繼續檢視  Trace  檔案的內容, Oracle  進一步執行的是如下操作:

select line#, sql_text from bootstrap$ where obj# not in (:1 , :2)  

--從 bootstrap$ 遞迴讀取相關的的SQL_TEXT, 由此可以看出是在建立並從資料檔案中裝載了  bootstrap$ 的內容之後, Oracle  開始遞迴的從該表中讀取信 息,載入資料。

那麼  bootstrap$ 中記錄的是什麼資訊呢? 在資料庫中, bootstrap$ 是一張實際存在的系統表:

再具體 看一下這張表的內容 :

        從這些語 句中可以看出, bootstrap$  中實際上是記錄了一些資料庫系統基本物件的建立語句。

而從10046 trace 日誌之後的相關語句資訊可以看出 Oracle  通 過  bootstrap$ 進行引導,讀取相關物件的ddl語句之後進一步建立相關的重要物件,從而啟動了資料庫。

        bootstrap$ 表在資料庫的啟動中是非常重要,如果   bootstrap$ 表發生損壞,將影響整個資料庫的啟動。

以下測試修改 bootstrap$ 表:

僅修改某些資料,貌似並不影響pdb的啟動,但如果重啟整資料庫呢?

重啟啟動資料庫後便因   bootstrap版本不一致而導致open 失敗,從而終止了例項, 在這種情況下,最好的方式是從備份中進行不完全恢復。


7、在從   bootstrap$引導初始化之後,便是載入其他資料庫資訊,包括許可權,job,過程,awr相關等,之後便完成了整個pdb的啟動。


      從以上pdb的啟動整個過程,相對於原來非多租戶例項, 其實總體流程與原來區別並不大, 不同之處是在pdb優先讀取 PDB_SPFILE$來初始化資料庫的引數,之後仍更新pdb的相關狀態資訊。


三、小結:

    oracle 12c 多租戶確實給我們帶來極大的便利,但同時伴隨的問題也是不少,其中遭遇到的各種bug也是莫名其妙。而從啟動過程分析,12c pdb實際也和原來非多租戶模式那樣差不多,只是在原來的基礎上一分為多,其中會新增進了更多的檢視來記錄pdb相關內容,pdb的啟動也需要用 bootstrap$做引導,並且與CDB共用同一份,pdb的引數可以自己獨立也可以繼承CDB的引數檔案等等,而對於pdb探究還在繼續,他遠不止我們想象的那麼簡單,但也絕不復雜。 





來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/29863023/viewspace-2135231/,如需轉載,請註明出處,否則將追究法律責任。

相關文章