原文地址:Oracle的exp/imp詳解 做者:jxlazzwhtml
備份概述
邏輯備份:
備份可分爲兩類 ,物理備份和邏輯備份linux
物理備份:該方法實現數據庫的完整恢復,但須要極大的外部存儲設備,例如磁帶庫,具體包括冷備份和熱備份。冷備份和熱備份(熱備份要求數據庫運行在歸檔模式下)都是物理備份,它涉及到組成數據庫的文件,但不考慮邏輯內容。
邏輯備份: 使用軟件技術從數據庫中導出數據並寫入一個輸出文件,該文件的格式通常與原數據庫的文件格式不一樣,只是 原數據庫中數據內容的一個映像。所以,邏輯備份文件只能用來對數據庫進行邏輯恢復,即數據導入,而不能按數據庫原來的存儲特徵進行物理恢復。邏輯備份通常 用於增量備份,即備份那些在上次備份之後改變的數據。
在進行邏輯備份時,首先要確認數據庫的字符集和操做系統的字符集是否一致,若是不一致則會報錯ora-00091,具體設置方法以下:
SQL> select * from v$nls_parameters where parameter in ('NLS_LANGUAGE','NLS_TERRITORY','NLS_CHARACTERSET');
PARAMETER VALUE
-------------------- --------------------
NLS_LANGUAGE AMERICAN
NLS_TERRITORY AMERICA
NLS_CHARACTERSET WE8ISO8859P1
$ export NLS_LANG=AMERICAN_AMERICA.WE8ISO8859P1
$ echo $NLS_LANG
AMERICAN_AMERICA.WE8ISO8859P1數據庫
exp緩存
能夠經過exp help=y或者imp help=y查看exp或imp的詳細參數,下面以exp爲例解釋參數意義
USERID:用戶名/口令
FULL:導出整個數據庫,只有擁有exp_full_database角色的用戶或者特權用戶如sys,system等才能進行全庫導出。 示例以下
exp "'/ as sysdba'" full=y
BUFFER:制定數據緩衝區大小,主要用於提升exp/imp速度,該單位爲字節,不能寫成buffer=1m的形式,應寫成字節爲單位的參數,如buffer=1048576
exp hr/hr file=t_b.dmp buffer= 1048576 tables=T
OWNER:須要導出的用戶,示例以下
exp "'/ as sysdba'" owner=\(hr,scott\) file=hr_scott.dmp
上例中因爲是在linux平臺進行測試的,須要對 owner=\(hr,scott\)使用\進行轉義
FILE:輸出文件
TABLES:須要導出的表
COMPRESS:導入到一個區 (Y) 。主要目的是爲了消除存儲碎片,以保證某張表的全部記錄都存儲在連續的空間裏。 可是負面效應很明顯, 若是該參數值爲y,則會將高水位線如下的全部extent導入到一個區中, 所以在導入時頗有可能出現,明明表中數據不多,可是卻花了不少時間在創建的extent上。 且自oracle9i開始,使用了本地管理的表空間,存儲碎片的問題應該比低版本好多了,筆者我的建議將compress設爲n。可參加以下實驗過程
SQL> create table t as select * from dba_objects;
Table created.
SQL> select segment_name,bytes/1024/1024 MB,blocks,extents,initial_extent from user_segments where segment_name='T';
SEGMENT_ MB BLOCKS EXTENTS INITIAL_EXTENT
-------- ---------- ---------- ---------- --------------
T 6 768 21 65536
採用delete的方式刪除表中數據,不下降HWM
SQL> delete from t;
50625 rows deleted.
SQL> commit;
Commit complete.
SQL> select segment_name,bytes/1024/1024 MB,blocks,extents,initial_extent from user_segments where segment_name='T';
SEGMENT_ MB BLOCKS EXTENTS INITIAL_EXTENT
-------- ---------- ---------- ---------- --------------
T 6 768 21 65536
將compress設爲n和y分別對t表進行兩次導出
exp hr/hr tables=t file=t_n.dmp compress=n
exp hr/hr tables=t file=t_y.dmp compress=y
刪除t表
SQL> drop table t purge;
Table dropped.
導入compress值爲y的dmp文件
imp hr/hr file=t_y.dmp fromuser=hr touser=hr;
查詢t表初始extent大小
SQL> select segment_name,bytes/1024/1024 MB,blocks,extents,initial_extent from user_segments where segment_name='T'
SEGMENT_ MB BLOCKS EXTENTS INITIAL_EXTENT
-------- ---------- ---------- ---------- --------------
T 6 768 6 6291456
查看建表語句
SQL> select dbms_metadata.get_ddl('TABLE','T','HR') FROM DUAL;
CREATE TABLE "HR"."T"
( "OWNER" VARCHAR2(30),
"OBJECT_NAME" VARCHAR2(128),
"SUBOBJECT_NAME" VARCHAR2(30),
"OBJECT_ID" NUMBER,
"DATA_OBJECT_ID" NUMBER,
"OBJECT_TYPE" VARCHAR2(19),
"CREATED" DATE,
"LAST_DDL_TIME" DATE,
"TIMESTAMP" VARCHAR2(19),
"STATUS" VARCHAR2(7),
"TEMPORARY" VARCHAR2(1),
"GENERATED" VARCHAR2(1),
"SECONDARY" VARCHAR2(1)
) PCTFREE 10 PCTUSED 40 INITRANS 1 MAXTRANS 255 NOCOMPRESS LOGGING
STORAGE(INITIAL 6291456 NEXT 1048576 MINEXTENTS 1 MAXEXTENTS 2147483645
PCTINCREASE 0 FREELISTS 1 FREELIST GROUPS 1 BUFFER_POOL DEFAULT)
TABLESPACE "USERS"
再次刪除t表
SQL> drop table t purge;
Table dropped.
導入compress值爲n的dmp文件
imp hr/hr file=t_n.dmp fromuser=hr touser=hr;
查詢t表初始extent大小
SQL>select segment_name,bytes/1024/1024 MB,blocks,extents,initial_extent from user_segments where segment_name='T'
SEGMENT_ MB BLOCKS EXTENTS INITIAL_EXTENT
-------- ---------- ---------- ---------- --------------
T .0625 8 1 65536
查詢建表語句
SQL>select dbms_metadata.get_ddl('TABLE','T','HR') FROM DUAL;
CREATE TABLE "HR"."T"
( "OWNER" VARCHAR2(30),
"OBJECT_NAME" VARCHAR2(128),
"SUBOBJECT_NAME" VARCHAR2(30),
"OBJECT_ID" NUMBER,
"DATA_OBJECT_ID" NUMBER,
"OBJECT_TYPE" VARCHAR2(19),
"CREATED" DATE,
"LAST_DDL_TIME" DATE,
"TIMESTAMP" VARCHAR2(19),
"STATUS" VARCHAR2(7),
"TEMPORARY" VARCHAR2(1),
"GENERATED" VARCHAR2(1),
"SECONDARY" VARCHAR2(1)
) PCTFREE 10 PCTUSED 40 INITRANS 1 MAXTRANS 255 NOCOMPRESS LOGGING
STORAGE(INITIAL 65536 NEXT 1048576 MINEXTENTS 1 MAXEXTENTS 2147483645
PCTINCREASE 0 FREELISTS 1 FREELIST GROUPS 1 BUFFER_POOL DEFAULT)
TABLESPACE "USERS"
可 以看到當compress爲y時,exp將數據導入到一個extent中,而在imp導入的時候則體現爲改變原有表的存儲參數,將初始化extent增大 到了6291456,我的建議一般狀況下將compress設置爲n,避免因爲初始extent過大,給下降HWM帶來的沒必要要麻煩。
RECORDLENGTH:IO記錄的長度
DIRECT:直接路徑 (N)。
傳統模式導出和直接路徑導出的原理
傳 統模式導出至關於使用select語句從表中取出數據,數據從磁盤上先讀到buffer cache中,記錄被轉移到一個評估檢測的緩衝區中,數據通過語法檢測後沒有問題,將數據傳給PGA,最後寫入導出的文件中。若是使用Direct Path模式導出,數據直接從磁盤上讀取到導出的PGA中:記錄直接被轉換導出會話的私有buffer中。這也就是意味着SQL語句處理層被忽略掉了,因 爲數據已是符合導出的格式了,不須要其餘的轉換處理了。數據直接被傳送給導出的客戶端,最後寫入導出文件。過程可概況以下
direct=n datafile---->sga----->pga----->dump
direct=y datafile---->pga----->dump
傳統模式導出和直接路徑導出的差別
Direct Path導出模式速度上明顯快於Conventional Path導出模式,由於Direct Path導出模式忽略了SQL語句處理這一層。
當使用Direct Path導出模式的時候,能夠增大參數RECORDLENGTH的值來提升導出的性能。導出的性能主要取決如下的因素:DB_BLOCK_SIZE、導出 表上列的類型、導出文件的I/O層(主要是指導出文件儘可能要和數據庫的數據文件在不一樣的磁盤上,避免I/O上的競爭)。通常來講,參數 RECORDLENGTH設置爲操做系統I/O的block size或者是DB_BLOCK_SIZE的整數倍,例如65535。
使用哪一種模式導出數據都不會影響導入數據,也就是說導入數據的時間是同樣的。
傳統模式導出和直接路徑導出的限制
Direct Path導出模式只能使用命令行或者參數文件的方式來導出,不能使用交互式的方式導出數據,只有Conventional Path導出模式可使用交互式的方式。
Direct Path導出模式不能用於導出傳輸表空間,即設置參數TRANSPORT_TABLESPACES=Y,其餘的FULL、USER、TABLE模式都可以使用Direct Path導出模式。
在Oracle8i之前的版本里面,若是表裏面存在LOB的對象,是不能使用Direct Path導出模式導出表的,若是使用Direct Path導出模式導出表,那些存在LOB對象的記錄是不會被導出的。自從Oracle8i以後,這種限制就被取消了。對於Oracle8i以後的版本,如 果使用Direct Path導出模式導出表,那些存在LOB對象的記錄是會自動以Conventional Path導出模式來導出。可是若是你用低於Oracle8i的客戶端的exp工具的Direct Path導出模式導出Oracle8i以上的數據庫存在LOB對象的表,那些包含LOB的記錄仍是一樣不會被導出。
Exp工具中的QUERY參數只能用於Conventional Path導出模式,QUERY參數容許導出一個表的知足必定條件的部分記錄。
Exp工具中的BUFFER參數只能用於傳統模式導出,BUFFER參數設置了用於fetch記錄的緩存的大小,以字節爲單位,即在array中最大數量的記錄。
參數RECORDLENGTH指定文件記錄的最大長度,以字節爲單位,即導出I/O的buffer,最大爲65535。這個參數決定了在沒寫入導出文件中緩存中堆積數據的多少。若是沒有設置這個參數,取決於操做系統平臺,在大多數平臺的默認值是1024字節。
只有當環境變量中的NLS_LANG設置成跟導出數據庫中的字符集一致的時候才能使用Direct Path導出模式導出數據。若是環境變量中的NLS_LANG和數據庫的字符集不一致的時候,導出就會報相似下面的錯誤:
EXP-41 "Export done in server's UTF8, different from user's character set WE8ISO8859P1"
EXP-0 "Export terminated unsuccessfully".
這種限制只對於Oracle8i及其更低版本的Oracle有效,Oracle8i以上的版本不會出現此類錯誤。
DIRECT=Y 參數定義了 使用直接路徑方式導出 ,RECORDLENGTH參數定義了Export I/O緩衝的大小,做用相似於常規路徑導出使用的BUFFER參數。建議設置RECORDLENGTH參數爲最大I/O緩衝,即65535(64kb)。其用法以下
exp userid=system/manager full=y direct=y recordlength=65535 file=exp_full.dmp log=exp_full.log
GRANTS:導出權限 (Y)
INCTYPE:增量導出類型,已廢除
INDEXES:導出索引 (Y)
RECORD:跟蹤增量導出 (Y) ,已廢除
TRIGGERS:導出觸發器 (Y)
LOG:屏幕輸出的日誌文件
STATISTICS:在導出文件中保留對象的統計信息,默認值ESTIMATE,還能夠爲compute或者none。若是導出時出現
EXP-00091: Exporting questionable statistics
能夠考慮將 STATISTICS設置爲NONE
ROWS:肯定表中的數據行是否導出,默認爲Y,導出
QUERY:用於導出表的子集的select子句,示例以下
exp hr/hr file=emp_q.dmp tables=employees query=\"where hire_date \>to_date\(\'1999-01-01\'\,\'yyyy-mm-dd\'\)\"
PARFILE:參數文件名,能夠用以下方式導出
exp hr/hr parfile=parfile
$ cat parfile
file=t_p.dmp
compress=y
rows=y
tables=(t,empl%s)
使用parfile參數能夠對頻繁進行的導出操做進行反覆調用,同時也能夠避免不一樣操做系統之間須要對特定字符進行轉義的煩惱,以下例
exp hr/hr parfile=parfile
$cat parfile
file=t_p.dmp
compress=y
rows=y
tables=employees
statistics=none
query="where hire_date>to_date('1999-01-01','yyyy-mm-dd')"
CONSISTENT:在導出時,將影響正在導出的表的事務設爲只讀,主要做用於嵌套表和分區表,默認爲N。
CONSTRAINTS:導出的約束條件 (Y)
OBJECT_CONSISTENT:只在對象導出期間設置爲只讀的事務處理 (N)
FEEDBACK:每 x 行顯示進度,默認爲0
FILESIZE:每一個導出文件的最大大小
FLASHBACK_SCN:用於將會話快照設置回之前狀態的SCN
FLASHBACK_TIME:用於獲取最接近指定時間的SCN的時間
RESUMABLE:遇到空間不足時的錯誤時掛起,默認爲N,需與 RESUMABLE_NAME和 RESUMABLE_TIMEOUT一塊兒使用
RESUMABLE_NAME:用於標示哪一個會話須要使用 RESUMABLE選項,格式爲User USERNAME (USERID), Session SESSIONID, Instance INSTANCEID
RESUMABLE_TIMEOUT:RESUMABLE的等待時間,默認爲7200s,若是在指定時間內未解決問題,則操做中斷
TTS_FULL_CHECK:對TTS執行完整或部分相關性檢查
TABLESPACES:要導出的表空間列表,示例以下
exp "'/ as sysdba'" file=t_ts.dmp tablespaces=(users,example)
TRANSPORT_TABLESPACE 導出可傳輸的表空間元數據 (N)
直接備份到磁帶上
exp icdmain/icd rows=y indexes=n compress=n buffer=65536 feedback=100000 file=/dev/rmt0 log=exp.log tables=(tab1,tab2,tab3)
注:在磁盤空間容許的狀況下,應先備份到本地服務器,而後再拷貝到磁帶。出於速度方面的考慮,儘可能不要直接備份到磁帶設備
imp
imp的參數和exp的大體相同,下面是經常使用參數的解釋,與exp相同的這就再也不贅述
ignore:Oracle在恢復數據的過程當中,當導入某個表時,該表已經存在,就要根據ignore參數的設置來決定如何操做。若 ignore=y,Oracle不執行CREATE TABLE語句,直接將數據插入到表中,若是插入的記錄違背了約束條件,好比主鍵約束,惟一索引等,則出錯的記錄不會插入,但合法的記錄會添加到表中。若 ignore=n,Oracle不執行CREATE TABLE語句,同時也不會將數據插入到表中,而是忽略該表的錯誤,繼續導入下一個表。 -
注意:若是表中的字段並無惟一性約束,那麼在使用ignore=y的狀況下頗有可能插入重複數據。
indexes:在恢復數據的過程當中,若indexes=n,則表上的索引不會被恢復,可是對 LOB 索引, OID索引和 主鍵索引等系統自動生成的索引將無條件恢復。
indexfile:不進行導入操做而是將建立對象的文本保存到文件中,能夠經過編輯使用該文本文件建立數據庫對象。
fromuser,touser:這兩個參數需組合使用,能夠實現將源用戶的對象數據,導入到目標用戶架構底下的功能。這裏要注意,導入時的用戶須要有imp_full_database角色,示例以下
$ imp hr/hr fromuser=hr touser=czm file=hr_all.dmp
commit:默認值爲 COMMIT=N,及在沒插入玩一個對象後提交。 當COMMIT=Y時候是根據你BUFFER的大小決定每次提交的數量。對於包含了LONG、RAW、 DATE等類型的表,不論BUFFER設置多大,都是每插入一行進行提交。,設置commit=y能夠防止減小回滾段的壓力,但因爲頻繁提交,會帶來性能 上的影響,推薦使用COMMIT=N。
exp/imp的優化思路
一、傳統模式導出能夠考慮使用buffer參數調整buffer大小來提升導入、導出速度
二、考慮使用直接路徑導出配合 RECORDLENGTH參數
三、使用管道技術,減小壓縮時間。管道是一種僞文件. 它存在於內存中, 用於快速I/O操做. 管道的緩衝區採用先進先出機制, 即寫管道進程寫到緩衝區頭部而讀管道進程讀取管道尾部. 示 例以下
mknod /home/exppipe p
exp test/test@orcl file=/home/exppipe & gzip < /home/exppipe > exp.dmp.gz
imp system/passwd@orcl file=/home/exppipe fromuser=test touser=macro & gunzip < exp.dmp.gz > /home/exppipe
rm -rf /home/exppipe
三、減小I/O競爭。Import是一個I/O密集的操做,避免I/O競爭能夠加快導入速度。若是可能,不要在系統高峯的時間導入數據,不要在導入數據時運行job等可能競爭系統資源的操做。
四、增長排序區。不管是否導入索引,imp操做都頗有可能建立主鍵惟一索引,這須要進行大量的排序操做。所以8i之後經過在導入時擴大pga_aggregate_target,導入後改回原值的方法能夠提升imp速度
五、若是條件容許能夠採用indexes=n,時候再建立索引。
六、避免在業務高峯進行大數據量的導入、導出
常見問題及解決方法
數據庫對象已經存在
通常狀況, 導入數據前應該完全刪除目標數據下的表, 序列, 函數/過程,觸發器等;數據庫對象已經存在, 按缺省的imp參數, 則會導入失敗。若是用了參數ignore=y, 會把exp文件內的數據內容導入,若是表有惟一關鍵字的約束條件, 不合條件將不被導入若是表沒有惟一關鍵字的約束條件, 將引發記錄重複
字符集轉換
對於單字節字符集(例如US7ASCII),恢復時,數據庫自動轉換爲該會話的字符集(NLS_LANG參數);
對於多字節字符集(例如ZHS16CGB231280),恢復時,應儘可能使字符集相同(避免轉換),若是要轉換,目標數據庫的字符集應是輸出數據庫字符集的超集,不然報錯
數據庫對象有主外鍵約束
不符合主外鍵約束時, 數據會導入失敗,
解決辦法:
一、先導入主表, 再導入依存表
二、disable目標導入對象的主外鍵約束, 導入數據後, 再enable它們
導入大表時存儲分配失敗
默認的EXP時, compress = Y, 也就是把全部的數據壓縮在一個數據塊上。導入時, 若是不存在連續一個大數據塊, 則會導入失敗. 導出80M以上的大表時, 記得compress= N, 則不會引發這種錯誤.
imp和exp使用的字符集不一樣
若是字符集不一樣, 導入會失敗, 能夠改變unix環境變量或者NT註冊表裏NLS_LANG相關信息。導入完成後再改回來.
imp和exp版本不能往上兼容
能夠從低版本導入高版本,但不能從高版本導入到低版本。若是遇到遷移因版本不一樣的問題,能夠用低版本的export導出,到導入到高版本。服務器
轉自http://www.software8.co/shujuku/oracle/2466.html架構