Oracle DUL的工作原理和技術實現
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/,如需轉載,請註明出處,否則將追究法律責任。
相關文章
- MRAM工作原理技術
- 爬蟲的實現原理和技術進行講解爬蟲
- 快速理解容器技術的實現原理
- 【Mysql核心技術】聊聊事務的實現原理MySql
- PostgreSQL、Oracle/MySQL和SQL Server的MVCC實現原理方式OracleMySqlServerMVC
- 前端技術探秘-Nodejs的CommonJS規範實現原理前端NodeJS
- HTML程式碼混淆技術:原理、應用和實現方法詳解HTML
- 將強化學習引入NLP:原理、技術和程式碼實現強化學習
- Oracle 的Lgwr Worker的工作原理Oracle
- ☕【Java技術指南】「併發原理專題」AQS的技術體系之CLH、MCS鎖的原理及實現JavaAQS
- Oracle實時同步技術Oracle
- 七、真正的技術——CAS操作原理、實現、底層原始碼原始碼
- 蘋果超級簽名的實現過程、技術原理蘋果
- 石墨投影牆凸顯的優勢及實現的技術原理
- 單點登入原理與技術實現比較
- 物件池技術和通用實現GenericObjectPool物件Object
- 力軟敏捷開發框架工作流實現技術敏捷框架
- 微信域名防封檢測的技術原理及實現方式
- 技術分享| 基於 Etcd 的分散式鎖實現原理及方案分散式
- 大前端的技術原理和變遷史前端
- 前端路由的原理和實現前端路由
- Ingress-nginx工作原理和實踐Nginx
- 一圖看懂區塊鏈的工作原理、技術及用例區塊鏈
- 單點登入的原理、實現、及技術方案比較詳解
- 實現繼承的幾種方式及工作原理繼承
- 後端技術雜談2:搜尋引擎工作原理後端
- 走進JavaWeb技術世界4:Servlet 工作原理詳解JavaWebServlet
- ?【Alibaba微服務技術系列】「Dubbo3.0技術專題」回顧Dubbo2.x的技術原理和功能實現及原始碼分析(溫故而知新)微服務原始碼
- 工作之餘的技術
- ?【Alibaba中介軟體技術系列】「Nacos技術專題」配置中心載入原理和配置實時更新原理分析(上)
- ?【Alibaba中介軟體技術系列】「Nacos技術專題」配置中心載入原理和配置實時更新原理分析(中)
- [精華] RDMA技術原理分析、主流實現對比和解析
- 瞭解react、vue的一大核心技術:虛擬DOM的實現原理ReactVue
- LRU Cache的原理和python的實現Python
- 技術實踐丨GaussDB(DWS)運維管理功能“升級”的原理和使用運維
- Linux網路安全技術與實現第2章之原理及實驗Linux
- 虛擬現實技術
- 從 Flutter 原始碼看 InheritedWidget 內部實現原理 | 掘金技術徵文Flutter原始碼