Library cache內部機制詳解

dawn009發表於2015-02-25

Library cache是Shared pool的一部分,它幾乎是Oracle記憶體結構中最複雜的一部分,主要存放shared curosr(SQL)和PLSQL物件(function,procedure,trigger)的資訊,以及這些物件所依賴的table,index,view等物件的資訊。

Library cache需要解決三個問題:

1.快速定位的問題:Library cache中物件眾多,Oracle如何管理這些物件,以便服務程式可以迅速找到他們需要的資訊。比如某個服務程式需要迅速定位某個SQL是否存在於Library cache中。

2.關係依賴的問題:Library cache中的物件存在複雜的依賴關係,當某個objec失效時,可以迅速將依賴其的物件也置為失效狀態。比如某個表發生了結構變化,依賴其的SQL語句需要重新解析。

3.併發控制的問題:Library cache中必須有一個併發控制的機構,比如鎖機制,來管理大量共享物件的併發訪問和修改的問題,比如某個SQL在重新編譯的同時,其所依賴的物件不能被修改。

Library cache結構:

Oracle利用hash table結構來解決library cache中快速定位的問題,hash table就是很多hash bucket組成的陣列:

原理與buffer cache中定位block的方式相同,將物件資訊(比如SQL)hash定位到某個hash bucket中,然後順序掃描bucket中的 List,實現快速定位物件的目的。

Library cache handle是物件的一個指標,其中的namespace屬性表示其指向的物件的型別:比如CRSR(Cursor),TABL(Table),INDX(Index) ,PROD(Procedure),TRIG(Trigger)等等。

LCO(Library cache object)是handel指向的物件,包含了以下幾個部分的內容:

1.dependency table:

指向本物件所依賴的物件,比如:select * from emp這個cursor的物件,依賴emp這個表,這裡指向了emp這個表的handle。

2.child table:

指向本物件的子物件,比如某個遊標的子游標。子游標是指SQL文字相同,但是SQL的實際含義不同的情況,比如執行的使用者不同,執行計劃不同,執行的環境不同等等,我們一般稱之為SQL的不同版本。一個SQL至少包含一個父遊標和一個子遊標。

3.authorization table:

物件的授權資訊。

4.type

Library cache object的type,包括:shared cursor,index,table,cluster,view,synonym,sequence,procedure,function,package,table body,package body,trigger等等。

5.data blocks

data block是一個指標,指向了data heap,即存放真實資料的地方,主要包括:diana tree, p-code, source code, shared cursor context area等等,如下圖:

Library cache物件依賴關係:

物件依賴關係是利用LCO中的dependency table來完成的,我們設想以下的情況,用來說明物件間的依賴關係:

兩個共享遊標:

SQL1: select * from emp;

SQL2: select * from emp和select a.name from emp a,dept b where a.dept_id=b.id and b.name=:1;

SQL1產生了兩個子游標,也就是SQL文字相同的兩個不同版本,他們同時依賴emp表。SQL2只有一個版本,因為每個遊標最少有一個子遊標,所以它只有一個子遊標,並且同時依賴dept表和emp表。

Library cache中的併發控制

Oracle利用Library cache lock和Library cache pin來實現併發控制,Library cache lock是在handle上獲取的,而Library cache pin則是在data heap上獲取。訪問物件時,首先必須獲取handle上的lock,然後將訪問的資料pin在記憶體中。lock的作用是控制程式間的併發訪問,而pin的作用是保證資料一致性,防止資料在訪問時被交換出去。

Library cache lock有三種模式:null,share,exclusive,Library cache pin有兩種模式:share,exclusive。下面詳細解釋在修改和訪問物件時,lock和pin的作用:

修改物件

編譯SQL或PLSQL物件,獲取該物件(cursor,procedure)handle上exclusive型別的lock,並且持有data heap上exclusive型別的pin,防止其他人讀取和修改。同時,在該物件所依賴的物件(table)上,必須持有一個share型別的lock和pin,防止在修改的過程中,被其他程式所修改。

訪問物件

訪問SQL或PLSQL物件,獲取該物件(cursor,procedure)handle上NULL型別的lock,並且持有data heap上share型別的pin,同時,在其依賴的物件(table)上持有share型別的lock和pin。如果一個procedure依賴另外一個function,那麼在被依賴的function上,也需要持有share型別的lock和pin。

NULL型別的lock比較特殊,它只存在於cursor和procedure等只讀物件上,它並不起到任何併發控制的作用,它更象是一個trigger,當物件失效時,通知所有訪問這個cursor的程式。比如:select * from emp這個SQL,依賴emp表,當emp表發生變化時,cursor上的NULL lock被打破,所有有訪問這個cursor的程式都會知道該物件已經失效。

當持有物件的library cache pin時,會在row cache中對相應的物件加鎖,就是row cache lock,阻止可能導致資料字典資訊混亂的DDL發生。

lock和pin的實現類似於enqueue,在每個handle上都有lock和pin的holder list和waiter list,用來儲存持有該資源和等待該資源的佇列。

阻塞分析

現實情況中,我們有一個資料庫中存在被應用大量頻繁訪問的procedure,當依賴的表發生變更時,導致該procedure失效,這時會出現大量的library cache lock和library cache pin的等待,堵塞應用訪問,造成了重大故障。出現這個問題的原因是:當procedure失效後,所有訪問該物件的程式都嘗試去編譯,大量程式嘗試獲取exclusive型別的lock和pin,出現了大量的等待。後續的Oracle版本作出了改進,當出現這種情況時,只允許第一個程式嘗試去編譯該物件,編譯通過後,所有的程式就可以併發訪問,避免了大量程式同時嘗試編譯的情況出現。

Library cache中的Latch:

Library cache中相關的latch包括:shared pool latch,library cahce latch,library cache lock latch,library cache pin latch。

Share pool latch的主要作用是分配或釋放空間時使用,從Oracle9i開始,sharedpool被分成了很多個subpool,由多個shared pool latch保護,Oracle開始支援更大的shared pool。

Library cache latch的主要作用是在hash bucket中定位handle時使用,library cache lock latch和library cache pin latch分別是獲取lock和pin時,需要取得的latch。

shared pool大小不合理,大量的硬解析以及SQL版本過多都可能導致shared pool latch和library cache latch的爭用。

從Oracle10g開始,Oracle正在逐步用mutex取代library cache中的latch,cursor:pin S和cursor:pin X相當於share和exclusive型別的library cache pin,cursor:pin S wait on X則表示share方式正在等待exclusive鎖定。

–EOF–

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

相關文章