巧用外部表備份歷史資料

jeanron100發表於2015-06-09
在很多的系統中,隨著時間的推移,都會沉澱大量的歷史資料。一般資料量達到一定程度都會考慮使用分割槽表來處理。根據業務規則,可能有些歷史資料隔一段時間就需要做清理了,這個時候歷史資料就需要在分割槽級進行清理。在不同的系統,不同廠商都有不同的實現方案。但是從資料安全形度來說,都需要做備份工作,也是預防萬一。
比如說我們存在一個表charge,就可能會有下面的幾種分割槽規則,
一種是按照日期來分割槽,這樣就能夠很清楚的定位到哪些天的資料可以清理。
比如 6月9日的充值記錄,分割槽表就為P_20150609,相關的一些分割槽如下:
P_20150609
P_20150610
P_20150611
如果需要做清理就需要使用exp或者expdp來根據分割槽匯出,這就完成了備份工作。
然後在分割槽層面使用truncate partition P_20150609或者drop partition P_20150609 來完成清理工作
還有一種方案是對於每個分割槽繫結一個對應的表空間,分割槽和表空間的情況如下。
P_20150609   TS_20150609
P_20150610   TS_20150610
P_20150611   TS_20150611
這樣的情況下,就需要維護對應的表空間,如果資料量較大,就需要新增多個資料檔案。
如果需要備份,還是採用exp或者expdp
對於清理工作,則可以直接刪除資料檔案或者使用truncate partition的形式。
可能分割槽規則不同,實現方式上都會有一些差別,但是總體來說,備份工作都是相對輕鬆的。清理工作的目標也很明確,要麼清空分割槽,要麼清理資料。
其實在這個時候,如果發生一些突發情況的時候,需要做資料恢復,就很鬱悶了。
對於第一種方案來說,分割槽已經被清理之後,如果在特定的情況下需要恢復,就顯得很困難。不行你可以試試,如果某些靠前的分割槽被刪除之後,再想新增就不是那麼容易的事情了。
而且就算行得通,imp,impdp的過程也會產生大量的歸檔檔案,比如說資料量在100G,結果費了一番功夫恢復之後,可能對於開發來說,只是做一些資料確認而已。確認之後還是需要做分割槽的清理。

對於第二種方案,可能維護起來的範圍較大,如果這種歷史表很多的時候,維護大量的表空間就有些應接不暇了。但是也勉強能夠接受。如果還是需要做資料恢復,可能開發也是做一些簡單的資料校驗和檢查。
這個時候我們還是需要建立一些相關的資料檔案,然後進行資料匯入imp或者Impdp來完成。這個難度和第一種方案是一致的,歸檔的消耗,二次清理還有無形之中的效能影響。

所以對於歷史表的這種處理,其實難度不在於備份和清理,難就難在一些恢復場景,比如備份了1T的表資料,在一些場景中需要做恢復,持續的時間,歸檔和效能,這種情況就會讓人很抓狂了。
其實方法方式有很多,使用外部表就是一種思路。在這種情況下,外部表看起來就全是優點,exp/expdp做不到的它都能做到。
首先空間佔用情況,在資料恢復的場景中,外部表不會佔用額外的資料空間,建立一個外部表就如同建立一個同義詞一樣,沒有額外的空間消耗。
其次來說說歸檔,外部表除了會生成極少量的日誌檔案(部分日誌檔案功能都可以禁用),對於歸檔幾乎就是零貢獻。
再次來說效能,這個部分就顯得有些微妙,可能仁者見仁,智者見智了。比如在一些場景中需要做資料恢復,可能涉及的資料極少,這個時候就可以輕鬆使用一些過濾條件來完成一些複雜的資料過濾工作。
比如說表charge存在一個分割槽P_20150609 裡面存放著100萬條記錄。
可能在資料恢復的時候需要檢查在晚上8點到9點的資料,假設有10萬條。這個時候假設我們基於分割槽P_20150609建立了外部表 charge_ext_20150609,則我們可以新增一些額外的過濾條件,建立出一個臨時表什麼的,
create table xxxx nologging as select *from charge_ext_20150609 where charge_date between xxx_8pm to xxx_9pm;
這個時候這種熱部署的優勢就顯現出來了,有了這些過濾後的資料,我們可以隨時解除安裝外部表。本身來說對於系統的影響應該說降到了最低。
如果真要做全表資料恢復,外部表也不遜色,我們可以使用insert /*+append*/的方式做資料插入,速度也還是不錯的。

我們來簡單演示一個案例。
備份,我們可以使用oracle_datapump來生成對應的外部表檔案

create table test.charge_ext_20150609
    ORGANIZATION EXTERNAL
    (TYPE ORACLE_DATAPUMP
     DEFAULT DIRECTORY xxxxx 
     LOCATION (
     ‘charge_201506609.dmp’……….
    )
    )
    parallel 4    as
    select /*+ parallel(t 4) */ * from charge partition(P_20150609) t;

drop test.mo1_memo_ext; --生成dump檔案之後,刪除外部表。

 

資料恢復
先載入外部表,這個過程就跟建立一個同義詞一樣快。

Create table charge_ext_20150609

   (    id number,object_id number,object_name varchar2(30),object_type varchar2(30),clob_test clob xxxx,charge_date date
   ) 
   ORGANIZATION EXTERNAL 
    ( TYPE ORACLE_DATAPUMP
      DEFAULT DIRECTORY "EXPDP_LOCATION"
      LOCATION(
‘charge_20150609.dmp’
       )
    )
   PARALLEL 2;

小量資料檢查
create table charge_tmp_20150609 as select *from charge_ext_20150609 where  charge_date between xxx_8pm to xxx_9pm;

全量恢復,對於資料全量恢復可以使用insert append的方式
Insert /*+append */ into xxx.charge select *from charge_ext_20150609;

Commit;

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

相關文章