http://czmmiao.iteye.com/blog/1522278
備份概述
邏輯備份:
備份可分為兩類,物理備份和邏輯備份
物理備份:該方法實現數據庫的完整恢復,但需要極大的外部存儲設備,例如磁帶庫,具體包括冷備份和熱備份。冷備份和熱備份(熱備份要求數據庫運行在歸檔模式下)都是物理備份,它涉及到組成數據庫的文件,但不考慮邏輯內容。
邏輯備份: 使用軟件技術從數據庫中導出數據並寫入一個輸出文件,該文件的格式一般與原數據庫的文件格式不同,只是 原數據庫中數據內容的一個映像。因此,邏輯備份文件只能用來對數據庫進行邏輯恢復,即數據導入,而不能按數據庫原來的存儲特征進行物理恢復。邏輯備份一般 用於增量備份,即備份那些在上次備份以后改變的數據。
在進行邏輯備份時,首先要確認數據庫的字符集和操作系統的字符集是否一致,如果不一致則會報錯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:這兩個參數可以組合使用,也可以分開使用。他們可以實現將源用戶的對象數據,導入到目標用戶schema底下的功能。這里要注意,導入時的用戶需要有imp_full_database角色,示例如下
導入一個或一組指定用戶所屬的全部對象
$imp system/manager file=full_all.dmp log=seapark fromuser=hr
$imp system/manager file=seapark log=seapark fromuser=(seapark,amy,amyc,harold)
將一個或一組指定用戶所屬的全部對象導入到另一個用戶下
$imp hr/hr fromuser=hr touser=czm file=hr_all.dmp
$imp system/manager file=tank log=tank fromuser=(seapark,amy) touser=(seapark1, amy1)
commit:默認值為 COMMIT=N,及在沒插入玩一個對象后提交。 當COMMIT=Y時候是根據你BUFFER的大小決定每次提交的數量。對於包含了LONG、RAW、 DATE等類型的表,不論BUFFER設置多大,都是每插入一行進行提交。設置commit=y可以防止減少回滾段的壓力,但由於頻繁提交,會帶來性能 上的影響,推薦使用COMMIT=N。
不同版本的EXP/IMP問題
一般來說,從低版本導入到高版本問題不大,麻煩的是將高版本的數據導入到低版本中,在Oracle9i之前,不同版本Oracle之間的EXP/IMP可以通過下面的方法來解決:
1、在高版本數據庫上運行低版本的catexp.sql;
2、使用低版本的EXP來導出高版本的數據;
3、使用低版本的IMP將數據庫導入到底版本數據庫中;
4、在高版本數據庫上重新運行高版本的catexp.sql腳本。
但在9i中,上面的方法並不能解決問題。如果直接使用底版本EXP/IMP會出現如下錯誤:
EXP-00008: ORACLE error %lu encountered
ORA-00904: invalid column name
這已經是一個公布的BUG,需要等到Oracle10.0才能解決,BUG號為2261,你可以到METALINK上去查看有關此BUG的詳細信息。
BUG歸BUG,我們的工作還是要做,在沒有Oracle的支持之前,我們就自己解決。在Oracle9i中執行下面的SQL重建exu81rls視圖即可。
CREATE OR REPLACE view exu81rls
(objown,objnam,policy,polown,polsch,polfun,stmts,chkopt,enabled,spolicy)
AS select u.name, o.name, r.pname, r.pfschma, r.ppname, r.pfname,
decode(bitand(r.stmt_type,1), 0,'', 'SELECT,')
|| decode(bitand(r.stmt_type,2), 0,'', 'INSERT,')
|| decode(bitand(r.stmt_type,4), 0,'', 'UPDATE,')
|| decode(bitand(r.stmt_type,8), 0,'', 'DELETE,'),
r.check_opt, r.enable_flag,
DECODE(BITAND(r.stmt_type, 16), 0, 0, 1)
from user$ u, obj$ o, rls$ r
where u.user# = o.owner#
and r.obj# = o.obj#
and (uid = 0 or
uid = o.owner# or
exists ( select * from session_roles where role='SELECT_CATALOG_ROLE')
)
/
grant select on sys.exu81rls to public;
/
常見問題及解決方法
數據庫對象已經存在
一般情況, 導入數據前應該徹底刪除目標數據下的表, 序列, 函數/過程,觸發器等;數據庫對象已經存在, 按缺省的imp參數, 則會導入失敗。如果用了參數ignore=y, 會把exp文件內的數據內容導入,如果表有唯一關鍵字的約束條件, 不合條件將不被導入如果表沒有唯一關鍵字的約束條件, 將引起記錄重復
字符集轉換
數據庫對象有主外鍵約束
不符合主外鍵約束時, 數據會導入失敗,
解決辦法:
1、先導入主表, 再導入依存表
2、disable目標導入對象的主外鍵約束, 導入數據后, 再enable它們
導入大表時存儲分配失敗
默認的EXP時, compress = Y, 也就是把所有的數據壓縮在一個數據塊上。導入時, 如果不存在連續一個大數據塊, 則會導入失敗. 導出80M以上的大表時, 記得compress= N, 則不會引起這種錯誤.
imp和exp使用的字符集不同
如果字符集不同, 導入會失敗, 可以改變unix環境變量或者NT注冊表里NLS_LANG相關信息。導入完成后再改回來.
參考至:http://baike.baidu.com/view/3781838.htm
http://www.itpub.net/thread-1220596-1-1.html
http://blog.csdn.net/gtlions/article/details/6972504
http://space.itpub.net/21634752/viewspace-706677
http://www.itpub.net/361441,2.html
http://asktom.oracle.com/pls/apex/f?p=100:11:0::::P11_QUESTION_ID:968789918647
http://www.itpub.net/thread-1196993-1-1.html
http://space.itpub.net/519536/viewspace-694577
http://www.xifenfei.com/2402.html
http://blog.csdn.net/tianlesoftware/article/details/4718366
http://space.itpub.net/35489/viewspace-613625
http://docs.oracle.com/cd/B10501_01/server.920/a96652/ch02.htm
