Oracle中邏輯導出Exp/導入Imp詳解sql
導入/導出是ORACLE倖存的最古老的兩個命令行工具,其實我歷來不認爲Exp/Imp是一種好的備份方式,正確的說法是Exp/Imp只能是一個好的轉儲工具,特別是在小型數據庫的轉儲,表空間的遷移,表的抽取,檢測邏輯和物理衝突等中有不小的功勞。固然,咱們也能夠把它做爲小型數據庫的物理備份後的一個邏輯輔助備份,也是不錯的建議。對於愈來愈大的數據庫,特別是TB級數據庫和愈來愈多數據倉庫的出現,EXP/IMP愈來愈力不從心了,這個時候,數據庫的備份都轉向了RMAN和第三方工具。下面說明一下EXP/IMP的使用。
如何使exp的幫助以不一樣的字符集顯示:set nls_lang=simplified chinese_china.zhs16gbk,經過設置環境變量,可讓exp的幫助以中文顯示,若是set nls_lang=American_america.字符集,那麼幫助就是英文的了。
EXP的全部參數(括號中爲參數的默認值):
USERID 用戶名/口令 如: USERID=duanl/duanl
FULL 導出整個數據庫 (N)
BUFFER 數據緩衝區的大小
OWNER 全部者用戶名列表,你但願導出哪一個用戶的對象,就用owner=username
FILE 輸出文件 (EXPDAT.DMP)
TABLES 表名列表 ,指定導出的table名稱,如:TABLES=table1,table2
COMPRESS 導入一個extent (Y)
RECORDLENGTH IO 記錄的長度
GRANTS 導出權限 (Y)
INCTYPE 增量導出類型
INDEXES 導出索引 (Y)
RECORD 跟蹤增量導出 (Y)
ROWS 導出數據行 (Y)
PARFILE 參數文件名,若是你exp的參數不少,能夠存成參數文件.
CONSTRAINTS 導出約束 (Y)
CONSISTENT 交叉表一致性
LOG 屏幕輸出的日誌文件
STATISTICS 分析對象 (ESTIMATE)
DIRECT 直接路徑 (N)
TRIGGERS 導出觸發器 (Y)
FEEDBACK 顯示每 x 行 (0) 的進度
FILESIZE 各轉儲文件的最大尺寸
QUERY 選定導出表子集的子句
下列關鍵字僅用於可傳輸的表空間
TRANSPORT_TABLESPACE 導出可傳輸的表空間元數據 (N)
TABLESPACES 將傳輸的表空間列表數據庫
IMP的全部參數(括號中爲參數的默認值):
USERID 用戶名/口令
FULL 導入整個文件 (N)
BUFFER 數據緩衝區大小
FROMUSER 全部人用戶名列表
FILE 輸入文件 (EXPDAT.DMP)
TOUSER 用戶名列表
SHOW 只列出文件內容 (N)
TABLES 表名列表
IGNORE 忽略建立錯誤 (N)
RECORDLENGTH IO 記錄的長度
GRANTS 導入權限 (Y)
INCTYPE 增量導入類型
INDEXES 導入索引 (Y)
COMMIT 提交數組插入 (N)
ROWS 導入數據行 (Y)
PARFILE 參數文件名
LOG 屏幕輸出的日誌文件
CONSTRAINTS 導入限制 (Y)
DESTROY 覆蓋表空間數據文件 (N)
INDEXFILE 將表/索引信息寫入指定的文件
SKIP_UNUSABLE_INDEXES 跳過不可用索引的維護 (N)
ANALYZE 執行轉儲文件中的 ANALYZE 語句 (Y)
FEEDBACK 顯示每 x 行 (0) 的進度
TOID_NOVALIDATE 跳過指定類型 id 的校驗
FILESIZE 各轉儲文件的最大尺寸
RECALCULATE_STATISTICS 從新計算統計值 (N)
下列關鍵字僅用於可傳輸的表空間
TRANSPORT_TABLESPACE 導入可傳輸的表空間元數據 (N)
TABLESPACES 將要傳輸到數據庫的表空間
DATAFILES 將要傳輸到數據庫的數據文件
TTS_OWNERS 擁有可傳輸表空間集中數據的用戶
關於增量參數的說明:exp/imp的增量並非真正意義上的增量,因此最好不要使用。windows
使用方法:
Exp parameter_name=value or Exp parameter_name=(value1,value2……)
只要輸入參數help=y就能夠看到全部幫助.
EXP經常使用選項
1.FULL ,這個用於導出整個數據庫,在ROWS=N一塊兒使用時,能夠導出整個數據庫的結構。例如:
exp userid=test/test file=./db_str.dmp log=./db_str.log full=y rows=n compress=y direct=y
注:在oracle10g中,userid這個是能夠不用寫的直接寫 用戶名/密碼 就能夠了像這樣:
exp test/test file=./db_str.dmp log=./db_str.log full=y rows=n compress=y direct=y 數組
優化EXP/IMP的方法:
當須要exp/imp的數據量比較大時,這個過程須要的時間是比較長的,咱們能夠用一些方法來優化exp/imp的操做。
exp:使用直接路徑 direct=y
oracle會避開sql語句處理引擎,直接從數據庫文件中讀取數據,而後寫入導出文件.
能夠在導出日誌中觀察到: exp-00067: table xxx will be exported in conventional path
若是沒有使用直接路徑,必須保證buffer參數的值足夠大.
有一些參數於direct=y不兼容,沒法用直接路徑導出可移動的tablespace,或者用query參數導出數據庫子集.
當導入導出的數據庫運行在不一樣的os下時,必須保證recordlength參數的值一致.
imp:經過如下幾個途徑優化
1.避免磁盤排序
將sort_area_size設置爲一個較大的值,好比100M
2.避免日誌切換等待
增長重作日誌組的數量,增大日誌文件大小.
3.優化日誌緩衝區
好比將log_buffer容量擴大10倍(最大不要超過5M)
4.使用陣列插入與提交
commit = y
注意:陣列方式不能處理包含LOB和LONG類型的表,對於這樣的table,若是使用commit = y,每插入一行,就會執行一次提交.
5.使用NOLOGGING方式減少重作日誌大小
在導入時指定參數indexes=n,只導入數據而忽略index,在導完數據後在經過腳本建立index,指定 NOLOGGING選項
導出/導入與字符集
進行數據的導入導出時,咱們要注意關於字符集的問題。在EXP/IMP過程當中咱們須要注意四個字符集的參數:導出端的客戶端字符集,導出端數據庫字符集,導入端的客戶端字符集,導入端數據庫字符集。
咱們首先須要查看這四個字符集參數。
查看數據庫的字符集的信息:
SQL> select * from nls_database_parameters;
PARAMETER VALUEsession
NLS_LANGUAGE AMERICAN
NLS_TERRITORY AMERICA
NLS_CURRENCY $
NLS_ISO_CURRENCY AMERICA
NLS_NUMERIC_CHARACTERS .,
NLS_CHARACTERSET ZHS16GBK
NLS_CALENDAR GREGORIAN
NLS_DATE_FORMAT DD-MON-RR
NLS_DATE_LANGUAGE AMERICAN
NLS_SORT BINARY
NLS_TIME_FORMAT HH.MI.SSXFF AM
NLS_TIMESTAMP_FORMAT DD-MON-RR HH.MI.SSXFF AM
NLS_TIME_TZ_FORMAT HH.MI.SSXFF AM TZH:TZM
NLS_TIMESTAMP_TZ_FORMAT DD-MON-RR HH.MI.SSXFF AM TZH:TZM
NLS_DUAL_CURRENCY $
NLS_COMP BINARY
NLS_NCHAR_CHARACTERSET ZHS16GBK
NLS_RDBMS_VERSION 8.1.7.4.1
NLS_CHARACTERSET:ZHS16GBK是當前數據庫的字符集。
咱們再來查看客戶端的字符集信息:
客戶端字符集的參數NLSLANG=< territory >.
language:指定oracle消息使用的語言,日期中日和月的顯示。
Territory:指訂貨幣和數字的格式,地區和計算星期及日期的習慣。
Characterset:控制客戶端應用程序使用的字符集。一般設置或等於客戶端的代碼頁。或者對於unicode應用設爲UTF8。
在windows中,查詢和修改NLS_LANG可在註冊表中進行:
HKEY_LOCAL_MACHINE\SOFTWARE\Oracle\HOMExx\
xx指存在多個Oracle_HOME時的系統編號。
在unix中:
$ env|grep NLS_LANG
NLS_LANG=simplified chinese_china.ZHS16GBK
修改可用:
$ export NLS_LANG=AMERICAN_AMERICA.UTF8
一般在導出時最好把客戶端字符集設置得和數據庫端相同。當進行數據導入時,主要有如下兩種狀況:
(1) 源數據庫和目標數據庫具備相同的字符集設置。
這時,只需設置導出和導入端的客戶端NLS_LANG等於數據庫字符集便可。
(2) 源數據庫和目標數據庫字符集不一樣。
先將導出端客戶端的NLS_LANG設置成和導出端的數據庫字符集一致,導出數據,而後將導入端客戶端的NLS_LANG設置成和導出端一致,導入數據,這樣轉換隻發生在數據庫端,並且只發生一次。
這種狀況下,只有當導入端數據庫字符集爲導出端數據庫字符集的嚴格超集時,數據才能徹底導成功,不然,可能會有數據不一致或亂碼出現。
不一樣版本的EXP/IMP問題
通常來講,從低版本導入到高版本問題不大,麻煩的是將高版本的數據導入到低版本中,在Oracle9i以前,不一樣版本Oracle之間的EXP/IMP能夠經過下面的方法來解決:
一、在高版本數據庫上運行底版本的catexp.sql;
二、使用低版本的EXP來導出高版本的數據;
三、使用低版本的IMP將數據庫導入到低版本數據庫中;
四、在高版本數據庫上從新運行高版本的catexp.sql腳本。
但在9i中,上面的方法並不能解決問題。若是直接使用低版本EXP/IMP會出現以下錯誤:
EXP-00008: orACLE error %lu encountered
orA-00904: invalid column name
這已是一個公佈的BUG,須要等到Oracle10.0才能解決,BUG號爲2261722,你能夠到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;
/
能夠跨版本的使用EXP/IMP,但必須正確地使用EXP和IMP的版本:
一、老是使用IMP的版本匹配數據庫的版本,如:要導入到817中,使用817的IMP工具。
二、老是使用EXP的版本匹配兩個數據庫中最低的版本,如:從9201往817中導入,則使用817版本的EXP工具。oracle