作業系統儲存管理和oracle資料庫(第一篇)

dbhelper發表於2015-01-17

在上大學的時候,學習作業系統感覺特別枯燥,都是些條條框框的知識點,感覺和實際的關聯不大。發現越是工作以後,在工作中越想深入瞭解,發現作業系統越發的重要。像現在的RHCE市場反響不錯,如果想深入地學習,就有很多作業系統的知識需要補補。在實踐中結合理論還是不錯的一種學習方法。自從接觸資料庫以後,越來越感覺到很多東西其實都是相通的,作業系統中的很多設計思想在資料庫中也有借鑑和改進之處。所謂大道至簡,其實就是這個道理。 

說到儲存管理,是作業系統中式最重要的資源之一。因為任何程式和資料等都需要佔有一定的儲存空間,儲存管理會直接影響到系統的效能。
儲存器是有主存和外存組成。對於外存,可能覆蓋面更廣,像硬碟,行動硬碟,光碟,磁帶,SSD等等都是外存的覆蓋範圍。主存大家很熟悉,這些年主存的大小也有了極高的提升,現在的伺服器配置中幾百G的記憶體都是很正常的。
--&gt儲存的管理技術
關於儲存的管理技術,先討論以下兩個部分。
固定分割槽
先來點作業系統的知識。
關於固定分割槽管理技術,就是把主存分為若干個固定大小的儲存區,每個分割槽提供給某一個作用使用,如果作業完成會把相應的儲存區歸還。
在多道作業系統中,主存中分割槽的個數是固定不變的,而且每個分割槽的大小也是固定不變的。如果分割槽總是大於作業,那麼就有很多分割槽沒有充分使用,產生碎片。
來結合資料庫來看一看(shared pool中的free list)
    在資料庫中,shared pool中的free list(bucket)管理和固定分割槽管理很相似。
shared pool中儲存單位是chunk,多個chunk組成一個連結串列,也叫做bucket.(free list),每個bucket都對chunk的大小都有一定的範圍,是一個連續的值,沒有交叉。
在10g,11g中都設定了255個bucket。
oracle的trace檔案中,每個bucket的大小都是固定的,
ora11g@rac1 trace]$ grep Bucket *18155*.trc
Bucket 0 size=32
Bucket 1 size=40
Bucket 2 size=48
Bucket 3 size=56
。。。
oracle在早期的版本中也碰到了不少的問題,在10g,11g中都對bucket的數目做了提升,而且分割槽的大小也做了調整。這是一個比較均衡的比例,能夠保證每次請求的大小都在bucket的範圍之內,儘量提高效率。

回到作業系統中,我們再補充幾點。
在儲存的管理中,儲存的分配和釋放都需要根據分割槽來說明。在固定分割槽中採用了一個儲存分塊表(MBT)來維護而儲存的區的資訊,儲存區的資訊在作業系統中有一個專有名詞叫做資料基,資料基聽起來挺抽象,其實理解起來還是蠻簡單的。
我們用下面的圖示來說明。我們假設下面的這個表格就是儲存分塊表,其中資料基就包括,儲存的分割槽大小,儲存位置還有狀態。

分割槽 大小 儲存位置 狀態
1 8k xxxxx used
2 8k xxxxx free
3 16k xxxxx used
4 16k xxxxx free
5 16k xxxxx used
6 32k xxxxx used


猛一看,上面的方式還是比較簡單而且可行的。但是還是固定分割槽的硬傷,主存利用率不高,對於進入主存中的作業大小我們也沒法預知,而且對於MBT表的管理冠絕還是不夠清晰。如果需要查詢哪些分割槽可用,需要重新分配的時候,就得遍歷整個表,遍歷了已經使用的分割槽,這樣分配的過程就比較長了。

這個時候可以參考一下
可變分割槽的多道管理技術
這種技術在一定程度上解決了固定分割槽帶來的問題,可變分割槽在主存中不會事先建立一個個分割槽,而是在作業進入主存的時候按照作業大小再來建立分割槽。
這樣的話,分割槽個數不固定,分割槽大小不固定,在oracle中也有一些相似之處。
 oracle中的deferred_segment_creation
比如說對於分割槽的不固定,在11g中有一個引數deferred_segment_creation,如果我們設定為true,那麼在建立之初是不會分配對應的分割槽的,直到開始插入資料之後,它才會根據插入的資料來建立分割槽。
oracle中的interval partitoning(可以參見http://blog.itpub.net/23718752/viewspace-1346319/)
如果根據需要動態的建立分割槽,而且分割槽的大小也不固定。
比如在資料庫的表空間管理中,我們可以指定分割槽的。
對於可變分割槽的資料基管理,是採用了兩個儲存分割槽表來管理的,已使用分割槽表(UBT)和空閒分割槽表(FBT),這樣就可以減少儲存分配和釋放的效能。
在這點上,oracle表空間中的資料字典管理方式是一致的。
oracle中是採用FET$, UET$ 兩個資料字典表來維護分割槽的資訊的。只是在資料基上會有一定的差別。
FET$和UET$的結構如下
SQL> desc fet$
 Name                                      Null?    Type
 ----------------------------------------- -------- ----------------------------
 TS#                                       NOT NULL NUMBER
 FILE#                                     NOT NULL NUMBER
 BLOCK#                                    NOT NULL NUMBER
 LENGTH                                    NOT NULL NUMBER

SQL> desc uet$
 Name                                      Null?    Type
 ----------------------------------------- -------- ----------------------------
 SEGFILE#                                  NOT NULL NUMBER
 SEGBLOCK#                                 NOT NULL NUMBER
 EXT#                                      NOT NULL NUMBER
 TS#                                       NOT NULL NUMBER
 FILE#                                     NOT NULL NUMBER
 BLOCK#                                    NOT NULL NUMBER
 LENGTH                                    NOT NULL NUMBER
這種方式在早期的oracle版本中採用,這種表空間管理方式叫資料字典管理。
但是在orale的不斷改進中,發現這種方式還是存在一定的問題,這種方式的資源消耗還是比較高的。對於這兩種資料字典表的dml操作,會產生較多的遞迴sql來間接完成對兩個資料字典表的更新,在更新的過程中也會存在事務,存在事務也就會產生一定的undo和redo。最後就是對於相鄰空閒空間的合併,在oracle中是透過smon程式來實現的。

回到作業系統,作業系統中對於資料基的管理還有一種方式,就是空閒儲存連結串列。
這種方式就是把空閒分割槽透過連結串列的形式串起來,形成了一條空閒儲存塊鏈。
這種技術在資料庫中可有一個很響亮的名字,在buffer cache中叫做LRU連結串列
在buffer cache中的實現方式也是類似的。當然在oracle中會採用其它的演算法和策略。oracle中是把buffer按照被使用的先後順序掛在LRU連結串列上,先被使用的buffer放在了連結串列的後面,後被使用的buffer掛載LRU連結串列的前面,如果buffer被修改的時候,buffer就會從LRU連結串列上取出。這樣始終保持LRU連結串列中都是可用的資料塊。

最後來簡單說一下可變分割槽的儲存演算法
目前主要有以下幾種,
最佳適用演算法
這種方式就是從所有未分配的分割槽中挑選一個最接近於作業尺寸且大於或者等於作業大小的分割槽分配。
最先適應法
按照分割槽序號從儲存分塊表中的第一個表目找找,把最先找到且大約等於作業大小的分割槽分配。
最壞適應法
把所有未分配的分割槽中挑選最大的且大於等於作業大小的分割槽分配。
點陣圖法
把所有的分割槽使用一個位來表示狀態,1表示塊已經被使用,0表示分割槽空閒。

在oracle中的儲存演算法可能更接近於最佳適應演算法,唯一的不同的是在oracle中採用了hash來該分配到哪個bucket。但是都會保證分配的空間是大於等於請求的大小。
而點陣圖法在表空間管理中也有相似的使用方式。
表空間的管理有兩種方式,資料字典管理和本地管理。
本地管理中會在資料檔案的頭部採用多個位來存放。這個bitmap類似下面的形式。
11110111001110100.....
1代表分割槽已被使用,0代表分割槽還是空閒,當程式需要分割槽的時候,只要掃描資料檔案的頭部的bitmap,就可以找到值為0的分割槽。分配了分割槽之後把它修改為1,釋放空間就會從1修改為0. 修改資料檔案頭部的操作速度快且不存在事務,就沒有redo,undo,更不會有遞迴sql。對於相鄰分割槽的合併來說,兩個連續的0就能說明是連續的空閒分割槽,所以也不需要再合併相鄰的可用分割槽了。

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

相關文章