教你如何成為Oracle 10g OCP - 第五章 記憶體元件與Oracle程式

tolywang發表於2010-05-23


5.1 用於與Oracle 資料庫伺服器建立連線

資料庫連線方式: 專用連線(Dedicated)和共享連線(Shared Server , MTS)

專用連線:  使用者在客戶端啟動一個ap,於是在客戶端本地啟動了一個使用者程式。 與Oracle伺服器成功建立連線
以後,就會在資料庫伺服器端生成一個對應的伺服器程式, 該伺服器程式作為使用者程式的代理程式,也叫影子程式,代
替客戶端使用者程式去執行各種命令並將結果返回。 使用者程式是不能直接訪問資料庫的。 這種模式下,使用者程式和伺服器
程式是一一對應的, 使用者程式終止,對應的伺服器程式也隨之終止。


共享連線:  在這種模式下,DBA可以定義伺服器程式的個數。 在啟動資料庫時, Oracle會預先在例項中建立指定個數
的伺服器程式, 這時使用者程式不再與伺服器產生一對一的關係, 而是一對多的關係, 一個使用者程式可以對應多個伺服器
程式, 多個伺服器程式都可以處理同一個使用者發出的不同命令。 比較少用 。


當使用者成功建立連線後, 會在伺服器端生成對應的伺服器程式, 同時建立一個session, 所謂session(會話),就是
一段記憶體空間, 這個空間記錄了使用者採用什麼應用程式連線到資料庫,客戶端機器名稱,以及哪個使用者名稱登入 等資訊。


容易混淆的概念:  connection & session 

連線:  物理概念,是客戶端到伺服器端的通訊通道,有本機,C/S,B/S三種結構。

 

 

5.2 深入shared pool


使用者端發出SQL請求,解析SQL語句,執行SQL語句

解析SQL語句:  檢查資料物件存在性,使用者操作許可權, 產生Oracle內部的執行計劃,指導SQL的執行過程, 解析是一個非常
消耗記憶體的過程,如果每次新的SQL都需要從頭到尾解析一遍的話,效率會非常低 。  


Oracle將SQL語句提煉成兩個部分, 一部分是SQL中的關鍵詞,表名及列名等 ; 另一個部分是SQL語句的動態部分,字面值value部分。
在處理的SQL語句中, 靜態部分可以認為是有限的, 但是動態部分由於字面值的變化而變得無限。 動態部分對解析的影響相對於靜態部分對
解析的影響是微乎其微, 對於相同靜態部分的SQL語句來說, 不同的動態部分所產生的解析結果(執行計劃)基本都是一樣的(除非表裡的資料
分佈極其不均勻)


0racle將使用者發出的SQL語句快取在記憶體中,每次處理新的一條SQL時,都會先在記憶體中檢視是否有相同的SQL語句,如果相同則減少最重要的
解析工作(也就是生成執行計劃),可以節省大量的CPU資源,反之如果沒有找到,必須從頭到尾進行完整的解析,這部分存放SQL語句的記憶體部分
就叫做共享池(shared pool).

共享池中存放的還有: SQL,PL/SQL程式碼,執行計劃,PL/SQL程式的機器碼,管理shared pool的記憶體結構,控制資訊等 。


繫結變數(bind variable): 也就是用一個變數來代替SQL中的字面值,那麼Oracle在shared pool中查詢到相同的SQL語句的
機率就很大 。 eg:  select * from t1 from c1=:v1 ; v1是變數,具體執行SQL時,才將字面值傳入。 因為靜態部分是有限
的, 同樣靜態部分的SQL因為繫結變數的使用變成了有限的一條SQL語句, 動態部分也變成有限(1條),從而很容易快取在記憶體中。  不使用
繫結變數導致SQL因為動態部分(字面值)的變化而變成無限,很難被快取到記憶體中。  只有使用了bind variable 才真正遵循了Oracle
引入shared pool 的根本思路,才能更有效的利用shared pool .


10g以前由於引數shared_pool_size決定共享池大小,10g或以後設定sga_target 來自動決定shared pool的大小。


Shared pool結構:  庫快取(library cache)和資料字典快取(dictionary cache) .

Library Cache:      存放最近執行的SQL語句,儲存過程,函式,解析樹以及執行計劃 等
Dictionary Cache :  存放SQL需要使用的資料字典資訊,包括表,列,許可權等,以資料行形式存在,而不是資料塊,也叫做row cache.
對於資料字典資訊,Oracle傾向於一直存在在shared pool裡面,不會將他們交換出記憶體。可以不用特別關注。


Library Cache是shared pool最重要的部分, 也是進進出出最活躍的部分 。

 

 

5.2.1 shared pool的記憶體結構

物理層面:  shared pool由許多記憶體塊組成,這些記憶體塊通常稱為chunk, 是shared pool中記憶體分配的最小單位,一個chunk中
所有的記憶體都是連續的 。

chunk可用的時候,它既不屬於library cache, 也不屬於dictionary cache,如果該chunk被用於存放SQL相關的資料時, 就
屬於library cache, 同樣如果該chunk被用於存放資料字典資訊時,該chunk屬於dictionary cache .


這些Chunk的分類:  free/recr/freeabl/perm

free:  這種chunk不包含有效物件,可以不受限制的被分配。
recr:  recreatable , 這種型別的chunk中包含的物件可以在需要的時候被臨時移走,並且在需要的時候重新建立,比如對於很多共享
SQL語句的chunk就是recreatable的。
freeabl:  這種chunk包含的物件都是曾經被session使用過的,並且隨後會被完全或部分釋放,這種型別的chunk不能臨時從記憶體移走,
因為他們是在處理過程中間產生的,如果移走的話就無法被重建。
perm :   permanent, 這種型別的chunk包含永久的物件,大型的permanent型別的chunk也可能含有可用空間,這部分可用空間可以
在需要的時候釋放回shared pool裡 。


在shared pool裡,可用的chunk(free型別)會被串起來成為可用連結串列(free list),或者也可以叫做bucket. 


小結:
連續的記憶體(Mem) --&gt 組成chunk --&gt 可用(free)的chunk --&gt 串聯起來 --&gt 成為可用連結串列(free list),或稱為bucket


當某個程式需要shared pool中的一個chunk時,該程式首先到符合所需空間大小的bucket上去掃描,以找到一個尺寸最合適的chunk,掃描
持續到bucket的最末端, 直到找到完全符合尺寸的chunk為止。 如果找到的尺寸比需要的尺寸要大, 這該chunk會被拆分成兩個chunk,一個
chunk被用來存放資料, 而另外一個則成為free型別的chunk, 並被掛到當前的該bucket上 。

如果該bucket 上不含有任何需要大小的尺寸的chunk, 那麼就從下一個非空的bucket上獲得一個最小的chunk, 如果在剩下的所有bucket
上都找不到合適可用的chunk, 則需要掃描已經使用的 recreatable 型別的chunk連結串列(free list), 從該連結串列上釋放一部分的chunk,
注意, 只有recreatable型別的 chunk 才是可以被臨時移出記憶體的。

當某個chunk正在被使用時,該chunk不能被移出記憶體, 比如某個SQL正在執行,這個SQL語句所使用的chunk是不能被移出記憶體的,該SQL所使用的
表,索引等物件所佔用的chunk也是不能被移出記憶體的。

當shared pool中無法找到足夠大小的連續記憶體(注: 連續記憶體才能組成chunk),就會報出ora-04031的錯誤資訊,可能是記憶體碎片 。
事實上,在Oracle報出ora-04031之前, 已經釋放了不少recreatable型別的chunk了,會產生不少可用記憶體,但沒有一個chunk能夠以連續
的實體記憶體提供所需的記憶體空間。
也就是說, 當我們在共享池中試圖分配大片的連續記憶體失敗的時候,Oracle首先清除池中當前沒使用的所有物件,使空閒記憶體塊合併。如果仍然沒有足夠
大單個的大塊記憶體滿足請求,就會產生ORA-04031 錯誤。


Shared pool latch :
latch就是輕量級的鎖,底層物件,用來保護對某個記憶體塊的併發訪問。 每個程式向記憶體塊中寫資料之前必須獲得latch,
寫完以後釋放latch, latch的獲取是序列話的, 一次只能一個程式能獲得latch, 獲取和釋放都很快 。

 

從邏輯層面來看,shared pool由 library cache和dictionary cache組成 。

元件關係:  當SQL語句進入library cache時, Oracle會先到dictionary cache中去找與SQL中表有關的資料字典資訊,比如表名,表的列,使用者許可權等資訊,如果dictionary cache中沒有這些資訊,則會將system表空間裡的資料字典資訊調入buffer cache記憶體中,讀取記憶體資料塊裡的資料字典內容, 然後將這些讀取出來的資料字典內容按照行的形式放入dictionary cache裡,從而在dictionary cache中構造出dc_tables,dc_segments,dc_columns 之類的物件。  然後再從dictionary cache的行資料中取出有關的列資訊放入library cache中。 


對於非常大的物件,可以讓Oracle為他們單獨從保留區域裡分配空間,而不是從chunk連結串列中來分配空間,透過shared_pool_reserved_size
設定,一般是shared_pool_size大小的 5%, 保留區域的可用chunk不會掛在bucket上 。

 


5.2.2 Library cache

library cache用於存放使用者發出的SQL語句,解析樹,執行計劃,PL/SQL程式塊,以及他們轉換後能被Oracle執行的程式碼 等。
為了對這些記憶體結構進行管理, library cache還存放了很多控制結構,包括lock,pin,dependency table 等。 library
cache 也存放了很多資料庫物件的資訊,包括表,索引等, 都是從資料字典快取中取得的, 如果使用者對物件資訊進行了修改,比如加了一個欄位,那麼這些修改會返回到dictionary cache中 。

在Library cache中存放的所有資訊單元都叫做物件,分為兩類: 儲存物件和過渡物件。 儲存物件包括表,檢視,索引,包等; 過渡物件即使用者發出的sql語句或pl/sql匿名程式塊 。

 

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

相關文章