Oracle DUL的工作原理和技術實現

talk_zhu發表於2021-01-10

       DUL工具是Oracle資料庫挽救資料的最後手段,你用到DUL的時候,大部分情況下,資料庫已經不能啟動了,甚至有些

資料 檔案已經損壞了。那麼DUL又是怎樣在這些極端的情況下把資料匯出來的呢?下面我們就來一步步的分析它的工作原理。

果你想自己開發一個類似的工具,這篇文章也會告訴你有那些工作要做,該怎樣去做。

       Oracle資料庫實際上是一堆資料的集合,資料儲存在表中,通過一些軟體來管理這些資料,其中讀取資料只是這些功能

中的一小部分。在這些資料中最重要的就是使用者資料,它們通常儲存在資料檔案中,按照一定的格式儲存。這些資料怎樣解

釋成我們看到的樣子,這就需要後設資料的幫忙了,通常我們把後設資料叫做資料字典。下面我們先來看看資料字典是什麼樣子。


資料字典

       Oracle的資料字典也是由一些表組成的。其中最主要的有obj$,tab$,col$這三張表,obj$表中指定了物件的名稱,對

象ID,物件的資料ID等,當然也指定了物件的屬主ID。tab$表指定了表的一些屬性,最主要的是它指定了表開始的位置,在

哪個資料檔案中,從哪個塊開始。col$表指定了表的列屬性,包括列的名稱,列ID,列在段中的ID,列的型別,長度等等,

有了col$中的資訊,Oracle就能解釋儲存在資料塊中的表的格式了。


表在資料檔案中的位置

       上面我們說過,tab$表中有兩個欄位指定了表開始的位置,一個叫FILE#,指示表在哪個資料檔案中,另一個叫BLOCK#,

指示表從哪個塊開始。這個開始的塊叫段頭塊,裡面包含了一個個extent地址範圍,叫做extent map,extent是由連續的數

據塊構成的。有了這個extent map,就可以從這些塊中讀取資料了,這些塊就是表的資料塊。如果一個表非常大,段頭塊並

不能包含所有的extent,那怎麼辦呢?Oracle會在這個塊中指定下一個extent map的塊地址,直到所有的extent map都列

舉完畢。

       有了上面的知識,我們就可以從資料檔案中讀取表的資料了。在開始之前,好像還有一點問題,怎樣從資料檔案中讀取

資料字典表呢?資料字典也是表,表的段頭位置又是從tab$中得到的,這時我們還沒有讀到tab$的資料,好像陷入死迴圈了。

別急,Oracle在啟動的時候會遇到跟我們一樣的問題,它怎麼來解決呢?原來Oracle啟動時,先在記憶體中建立一個叫做

bootstrap$的表,這個表中儲存了一些建表語句,其中就包括了上面提到的obj$,tab$和col$,有趣的是,在每個建表語句

的後面,還指示了這個表的段頭塊位置,那麼這下就方便了,直接到這個位置找到extent map,遍歷所有的extent map找到

屬於這個表的資料塊,解析資料塊中的內容,就可以得到資料字典的資訊了。

       看到這裡,你還有點困惑,那麼說明你思考的深入,是的,bootstrap$表的開始位置在哪裡呢?它儲存在1號資料檔案的

1號塊中,這個塊包含檔案頭資訊,裡面有個叫root dba的欄位,包含的地址就是bootstrap$表的段頭塊地址。


資料塊

       資料塊中包含了表中的資料,它也是有一定結構的,開始是塊頭資訊,事務資訊,下面是ITL,ITL大小是固定的,叫做事

務槽,塊中包含幾個事務槽,在事務資訊中指定。再後面就是資料頭資訊,緊接著是表目錄(table directory)資訊,後面是

行目錄(row directory),行目錄指定了每行資料的位置。再後面就是行資料了,行資料是從塊的底部往上來儲存的,所以

在行目錄和真正的資料之間可能會有一部分空閒的空間。資料塊的結構比較複雜,好在Oracle有一個工具叫做bbed,可以打

開一個資料塊,它詳細定義了這些資料結構,包含資料結構的各個欄位,可以方便的看到資料儲存的細節。


LONG資料型別

       LONG型別的資料一般比較長,很容易造成行連線,當然如果一個表建立時欄位過多,也會造成行連線,就是說一行資料

分佈在了兩個或多個資料塊之間,這時怎麼辦呢?Oracle在每行資料開始都有一個叫做fb的欄位,指示資料是否連線到了下一

個塊,如果到了下一個塊,那麼就會出現一個叫做nrid的欄位,用來指示後面的資料連線到了哪裡,這是一個地址,代表了在

哪一個塊的哪個偏移量。如果下一個塊還沒有完全容納這一行資料,那麼會有下一個nrid,一直連線下去,直到資料行結束。


LOB資料型別

       LOB是大物件資料型別,是為了替代LONG型別引入的,當資料量比較小時,它儲存在表的塊內,如果資料比較大,就存

儲在表外的一個段中,這個段叫做LOB段。LOB資料在LOB段中的位置,由一個叫做定位器的欄位來指定,英文名稱叫做Lob 

Locator,這個定位器儲存在表的資料塊中,這樣讀到LOB欄位時,就可以通過定位器找到LOB資料。


LOB Index

       其實,LOB的儲存是相當複雜的,預設的情況下,為了方便儲存,LOB列在表的資料塊中,不僅儲存了定位器,還儲存了

一些LOB資料塊的地址,通過這些地址把LOB資料讀出來。但是這些儲存的地址個數是有限制的,這取決於表資料塊中LOB信

息的長度,預設情況下最多是12個,如果超出了,就要用到定位器了,定位器不能直接找到LOB段的塊位置,實際上他是LOB 

index的一個鍵值,通過這個鍵,在LOB索引中找到一系列的LOB塊的地址,通過這些地址把LOB資料讀出來。


SecureFile LOB

       上面談到的LOB儲存格式叫做BasicFile LOB,從11g開始,Oracle引入了一種新的LOB儲存格式,叫做SecureFile LOB。

它幾乎把LOB index取消了,而是把LOB的塊地址直接放在了LOB段的頭塊中,通過頭塊中的地址可以直接讀取LOB資料。當

然如果LOB資料量很大很大,頭塊也放不下這麼多地址,那怎麼辦呢?Oracle在頭塊中設定了四個地址,分別叫做dba0,

dba1,dba2,dba3。這是一個四級的內部樹結構,dba0相當於一個葉子節點,管理了很多LOB資料塊地址,當dba0滿了,

就會出現dba1,是dba0的上級節點,它又管理了很多類似dba0的葉子,每個葉子節點塊都包含了很多LOB資料塊的地址,

dba1滿了,就會出現dba2節點,類推上去,到了dba3時,能管理的資料量已經遠超過了LOB資料量的最大限制,這樣所有

的LOB資料都能通過這個結構遍歷讀取了。


Recyclebin

       如果你刪除了表,從11g開始預設情況下並沒有真正刪除,而是把表名改變了,原來的表名儲存在了一個叫回收站的表中,

如果你改變了主意,還可以通過命令恢復回來,對誤刪了表是一個好訊息。由於它與普通表沒有區別,所以通過上面的知識,

我們就能恢復回來。


Truncate Table

       如果一個表被截斷了,那可能你就真的訪問不了原來的資料了,如果現在後悔了,也只能去撞牆了。用我們前面介紹的

方法能不能找回資料呢?找到表的段頭塊,dump出來看看,你會發現段頭塊中的extent map已經被清除了,這就沒法通過

extent map把資料遍歷出來了。辦法總是有的,資料不是都儲存在資料檔案中嗎?那我們把所有資料檔案中的塊都掃描一遍,

把跟這個表的ID一致的那些塊都找出來,然後從這些塊中把資料都分析出來,不就可以了嗎?只是花費的時間多一些,並且

要保證不能遺漏了資料檔案,實踐證明還是可以把資料讀出來的。


Drop Table

       有了上面截斷表的經驗,刪除的表也就好處理了。段頭塊的改變幾乎與截斷表是一樣的。與截斷表不同的是,你要先把

資料字典中刪除的記錄恢復出來,obj$,tab$,col$表中關於這個表的記錄都被刪除了,那麼怎樣恢復呢?記得前面我們提

到過在每行資料前面都有一個叫做fb的欄位,其實Oracle並沒有把這條資料清除掉,只是在fb欄位上做了一個標記,去除這

個標記,這些記錄就都恢復了。下面再把資料檔案掃描一遍,找到屬於這個表的塊,就能把資料恢復了。


資料字典損壞

       最嚴重的情況就是資料檔案中有部分已經損壞了,那麼就不能保證完全恢復資料了。那麼首先還是要嘗試讀取資料字典,

Oracle對基礎的資料字典表儲存的段頭塊位置都是固定的,找一個相同版本的資料庫,從bootstrap$表中查詢到資料字典的

段頭位置,或者從tab$中找到段頭位置,然後嘗試從這些地方匯出資料字典,如果能匯出資料字典,剩下的工作就跟前面一

樣了。

       最壞的情況就是系統表空間的資料檔案丟失或者嚴重損壞,已經無法匯出資料字典了,那麼這時怎麼辦呢?那麼只有通過

資料來重建資料字典了,還是把所有資料檔案掃描一遍,記錄段頭塊的位置,每個段頭塊會對應一個表或一個分割槽,這樣表的

段頭位置就找到了,接下來要做的就是重建col$中的欄位,主要是資料型別,長度等。有些資料型別的長度是固定的,比如日

期型別,時間戳型別,很好猜測。數字型別也有自己的特點比較好確定,剩下的就是字元型別了,大部分猜測不到的都可以先

當做字元型別處理。然後根據重建的資料字典匯出一部分資料,這時就要通過人工比對,把欄位型別確定清楚,然後就可以導

出資料了。


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

相關文章