專題實驗 EXP & IMP


導入導出時 oracle 提供的實用工具, 如果這些被導出的對象還存在其他的相關對象, 比如要被導出的表上還存在索引, 注釋等, 則導出工具會自動將這些相關的對象也提取出來, 並放入到導出的文件中去. 看來是將對象一起導出, 而非需要先在目標數據庫中創建對象, 然后再將數據導入.

可以實現跨平台.

相對於邏輯備份來說, 導入導出是將數據庫中的對象與數據存儲在一個文件中, 然后在導入到新的數據庫, 這是數據庫中邏輯文件的轉儲, 而物理備份, 備份的是數據所在的數據塊.

在執行導入過程中, 按照下面的順序導入表, 表里的數據以及相關對象:

1. 創建表結構

2. 導入表的數據

3. 創建相關索引

4. 導入觸發器

5. 對導入的表啟用完整性約束

6. 建立所有位圖, 函數以及其他索引

以上, 都是導入時, 自動進行的. 有時, 我們導入時, 在目標數據庫中已經存在了該表, 因為創建表結構在第一步, 所以導致后邊的操作都沒有進行, 這時我們可以使用ignor=y 這個參數, 這樣, 我們就可以把導出文件中包含的數據累加到該表中去.


10g 以后數據泵

oracle 10g 以后推出了數據泵(data pump), 與之前的導入導出工具類似, 但是他們之間最大的區別是, 數據泵只能在服務器端運行. 而不能將該轉儲文件導出到客戶端.

使用數據泵的優點:

  • 如果轉儲過程中出現問題, 可以實現續傳
  • 可以只處理某些對象, 或者不處理某些對象, 或者只處理某些對象中的滿足指定條件的數據 等
  • 在不實際執行導出的情況下, 估計整個導出工作需要占用多少磁盤空間
  • 通過 db link, 將遠程數據庫導出到轉儲文件
  • 通過 db link, 直接將遠程的, 位於其他主機上的數據庫里的數據導入到當前數據庫中, 從而實現跨平台的數據遷移.
  • 在導入時, 可以修改導入數據所在的schema名稱, 表空間名稱以及數據文件名稱
  • 通過采樣, 導出部分數據
  • 只導出元數據(比如表結構 等), 而不導出實際的數據, 而且在導出元數據的過程中, 還可以指定是否要啟用壓縮功能.
  • 可以進行並行操作.

數據泵在數據導出到服務器端時, 可以通過目錄對象(dirctory object)來控制生成的轉儲文件應該放在服務器端的那個目錄下. 目錄對象時數據庫中的一種對象, 代表服務器文件系統上的目錄結構, 通過在數據庫中使用這些目錄對象, 就可以在數據庫中, 對某個指定目錄下的文件進行讀取和寫入操作. 我們就不需要對文件系統路徑進行硬編碼.

在數據泵運行過程中, 主表(Master Table 簡稱MT)起到了關鍵性作用, 在MT表中, 保存了整個數據泵運行過程中的相關信息, 這些信息包括要處理的所有對象的信息, 當前正在處理的對象信息. 在啟動數據泵的時候, 如果我們制定了任務名稱, 則 MT 表名稱就等於任務名稱.

創建目錄對象: create directory my_dir as ‘/opt/mydir_exp’;

授權用戶讀寫該目錄對象: grant write on directory my_dir to hr;

演示:

在執行導出時, expdp 先創建 MT 表, 並將對象信息插入 MT 表以后, 開始執行實際的導出任務, 當所有對象都導出以后, 將 MT 表也一起導出到轉儲文件中, 等到導出任務成功完成或通過命令刪除了導出任務時, MT 表會自動被刪除. 如果導出任務異常終止, MT 表會保留.

在執行導入時, impdb 先將 MT 表從轉儲文件中讀出, 並寫入目標數據庫, 然后讀取 MT 表中所記錄的對象信息, 並根據讀取出來的對象名稱, 將這些對象從轉儲文件中提取出來, 並插入到目標數據庫里.

使用命令行方式, 類似於 exp/imp,

expdp help=y  查看導出時的參數

impdp help=y 查看導入時的參數.

例如:

 

EXPDP

~ 導出某個指定的表

expdp hr/hr directory=my_dir dumpfile=exp%U.dmp tables=(employees) job_name=EXP

~ 導出某幾個用戶

expdp system/oracle directory=my_dir dumpfile=exp%U.dmp schemas=(hr, oe)

~ 導出整個數據庫

expdp system/oracle directory=my_dir dumpfile=exp%U.dmp full=y parallel=4

一些高級應用:

~ 指定不導出某些對象

expdp system/oracle directory=my_dir dumpfile=exp%U.dmp parfile=exp_par.txt   其中, exp_par.txt 是我們之前先編輯好的參數文件.

vi exp_par.txt 如下:

exclude=table:”like ‘EMPLOYEES%’”   -- 表名大小寫敏感. table 后邊的內容類似sql 語句中的 where 條件, 在比如下邊的例子:

schemas=hr

exclude=table: “in (‘EMPLOYEES’, ‘DEPARTMENTS’)”

schemas=hr

~ 只導出指定類型的對象

expdp system/oracle directory=my_dir dumpfile=hr_oe.dmp parfile=exp_par.txt

其中, exp_par.txt

include = function

include = procedure

include = package

include = view:”like ‘PRODUCT%’”

schemas = hr, oe

~ 只導出符合條件的數據

expdp hr/hr directory=my_dir dumpfile=hr.dmp parfile=exp_part.txt

其中, exp_part.txt 為:

tables=(employees)

query=employees:“where department_id = 40 order by employee_id”

~ 對數據庫中的數據進行采樣以后, 導出采樣數據

expdp hr/hr directory=my_dir dumpfile=exp%U.dmp schemas=hr sample=30

expdp hr/hr directory=my_dir dumpfile=exp%U.dmp schemas=hr sample=employees:30  --只是 employees 30%采樣導出, 其他的表都正常導出

 
中斷導出任務以后, 從中斷處再次啟動導出任務

expdp hr/hr attach=EXP  -- 這個attach=EXP, 表示繼續EXP這個任務. 這樣就進入了任務的交互式界面,

help 可以看到在交互界面中的命令, 我們可以為任務增加或編輯些內容, 比如 add_file=40M, 等, 編輯完后, start_job 任務就開始繼續執行, 但是我們看不到,是在后台執行, 我們可以使用continue_client 該命令可以將任務在后台執行的進度體現到前台.

 

IMPDP

常用的參數:

remap_datafile: 用戶不同文件系統平台, 轉換文件路徑

remap_tablespace: 用於將對象從一個表空間導入到另一個表空間 比如: remap_tablespace=users:example 說明導出文件對象位於users表空間, 導入以后, 對象位於example表空間

remap_schema: 用於將對象從一個用戶下導入到另一個用戶下. 比如: remap_schema=hr:hjs 說明導出文件對象位於 hr用戶下, 導入以后, 對象位於 hjs用戶下.

~ 導入某個指定的表

impdp hjs/hjs directory=my_dir dumpfile=exp01.dmp table=(emp) remap_schema=hr:hsj remp_tablespace=users:example

~ 導入某幾個用戶

impdp system/oracle directory=my_dir dumpfile=exp01.dmp remap_schema=hr:hsj   將 hr 下的所有對象都導入 hsj.

~ 導入整個數據庫

impdp system/oracle directory=my_dir dumpfile=exp%U.dmp full=y

高級方法與 expdp 類似

比如:

impdp system/oracle directory=my_dir dumpfile=exp01.dmp parfile=imp_par.txt

其中 imp_par.txt 的內容為:

exclude=table: “in (‘EMPLOYEES’, ‘DEPARTMENTS’)”

remap_schema=hr:hjs

 


基本語法和實例:

1、EXP:


有三種主要的方式(完全、用戶、表)
1、完全:
exp icdmain/icd rows=y indexes=n compress=n buffer=65536 feedback=100000 full=y file=exp_.dmp log=exp.log

如果要執行完全導出,必須具有特殊的權限
2、用戶模式:
exp icdmain/icd owner=icdmain rows=y indexes=n compress=n buffer=65536 feedback=100000 file=exp.dmp log=exp.log
3、表模式:
exp icdmain/icd rows=y indexes=n compress=n buffer=65536 feedback=100000 volsize=0 file=exp.dmp log=exp.log tables=tab1,tab2,tab3

exp help=y  可以用來查看相關的參數配置

 

2、IMP:


具有三種模式(完全、用戶、表)與 EXP 對應 
1、完全:
IMP SYSTEM/MANAGER BUFFER=64000 FILE=C:\FULL.DMP FULL=Y
2、用戶模式:
IMP SONIC/SONIC BUFFER=64000 FILE=C:\SONIC.DMP FROMUSER=SONIC TOUSER=SONIC
這樣用戶SONIC的所有對象被導入到文件中。必須指定FROMUSER、TOUSER參數,這樣才能導入數據。
3、表模式: 
IMP SONIC/SONIC BUFFER=64000 FILE=C:\SONIC.DMP OWNER=SONIC TABLES=(SONIC)
這樣用戶SONIC的表SONIC就被導入。

imp help=y 可以用來查看相關參數配置

 

示例

4.1 oracle創建表空間,創建用戶

//創建臨時表空間

create temporary tablespace test_temp

tempfile ‘/u01/app/oracle/oradata/orcl/test_temp01.Dbf'

size 32m autoextend on next 32m maxsize 2048m

extent management local;

//創建數據表空間

create tablespace test_data logging

datafile '/u01/app/oracle/oradata/orcl/test_data01.dbf' ­

size 32m autoextend on

next 32m maxsize 2048m

extent management local;

//創建用戶並指定表空間

create user username identified by password

default tablespace test_data

temporary tablespace test_temp;

//給用戶授予權限 ­

grant connect,resource to username;

先創建一個用戶和表空間,用戶名david,密碼david.在這個表空間下創建一個表:tianle。隨便插入些數據。代碼如下:

SQL> create tablespace test_data

3 datafile '/u01/app/oracle/oradata/orcl/test_data01.dbf'

4 size 5m;

Tablespace created.

SQL> create user david identified by david default tablespace test_data;

SQL> grant connect,resource to david;

SQL> conn david/david

SQL> create table tianle(id number, content varchar2(100));

SQL> set wrap off

SQL> column id format a20;

SQL> column content format a50;

4.2 表模式備份 與 恢復

備份:

[oracle@roy orcl]$ exp david/david rows=y indexes=n compress=n buffer=65536 file=exp_tianle_090101.dmp log=exp_tianle_090101.log tables=(tianle);

恢復:

[oracle@roy orcl]$ imp david/david fromuser=david touser=david rows=y indexes=n commit=y buffer=65536 file=exp_tianle_090101.dmp log=imp_tianle_090101.log tables=(tianle); ­

4.3 用戶模式備份與恢復

備份:

[oracle@roy orcl]$ exp david/david owner=david rows=y indexes=n compress=n buffer=65536 file=exp_david__090101.dmp log=exp_david_090101.log; ­

恢復:

[oracle@roy orcl]$ imp david/david fromuser=david touser=david rows=y indexes=n commit=y buffer=65536 file=exp_tianle_090101.dmp log=exp_tianle_090101.log; ­

4.4 完全模式備份與恢復

備份:

[oracle@roy orcl]$ exp david/david rows=y indexes=n compress=n buffer=65536 full=y file=exp_fulldatabase_090101.dmp log=exp_fulldatabase_090101.log; ­

恢復

[oracle@roy orcl]$ imp david/david rows=y indexes=n commit=y full=y ignore=y buffer=65536 file=/tmp/exp_fulldatabase_090101.dmp log=/tmp/imp.log;


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

2. OWNER和TABLE,這兩個選項用於定義EXP的對象。OWNER定義導出指定用戶的對象;TABLE指定EXP的table名稱,例如:
exp userid=test/test file=./db_str.dmp log=./db_str.log owner=duanl
exp userid=test/test file=./db_str.dmp log=./db_str.log table=nc_data,fi_arap

3.BUFFER和FEEDBACK,在導出比較多的數據時,我會考慮設置這兩個參數。例如:
exp userid=test/test file=yw97_2003.dmp log=yw97_2003_3.log feedback=10000 buffer=100000000 tables=WO4,OK_YT

4.FILE和LOG,這兩個參數分別指定備份的DMP名稱和LOG名稱,包括文件名和目錄,例子見上面。

5.COMPRESS參數不壓縮導出數據的內容。用來控制導出對象的storage語句如何產生。默認值為Y,使用默認值,對象的存儲語句的init extent等於當前導出對象的extent的總和。推薦使用COMPRESS=N。

IMP常用選項
1、FROMUSER和TOUSER,使用它們實現將數據從一個SCHEMA中導入到另外一個SCHEMA中。例如:假設我們做exp時導出的為test的對象,現在我們想把對象導入用戶:
imp userid=test1/test1 file=expdat.dmp fromuser=test1 touser=test1

2、IGNORE、GRANTS和INDEXES,其中IGNORE參數將忽略表的存在,繼續導入,這個對於需要調整表的存儲參數時很有用,我們可以先根據實際情況用合理的存儲參數建好表,然后直接導入數據。而GRANTS和INDEXES則表示是否導入授權和索引,如果想使用新的存儲參數重建索引,或者為了加快到入速度,我們可以考慮將INDEXES設為N,而GRANTS一般都是Y。例如:imp userid=test1/test1 file=expdat.dmp fromuser=test1 touser=test1 indexes=N

優化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 VALUE
------------------------------ --------------------------------------------------------------------------------
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是當前數據庫的字符集。

我們再來查看客戶端的字符集信息:
客戶端字符集的參數NLS_LANG=<language>_< territory >.<Clients Characterset>. 對應含義如下:
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可以通過下面的方法來解決:
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號為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的版本:
1、總是使用IMP的版本匹配數據庫的版本,如:要導入到817中,使用817的IMP工具。
2、總是使用EXP的版本匹配兩個數據庫中最低的版本,如:從9201往817中導入,則使用817版本的EXP工具


full

exp 時, 使用full 將導出全部內容(全部用戶的權限, 全部數據, 全部數據庫結構等等), 如果是單純的邏輯導出還好, 這里還會導出創建 表空間的腳本, 從而自動創建表空間, 所以, 使用 full 的情況:

1. 目標數據庫與來源數據庫在結構上完全一樣, 例如一個測試數據庫, 一個正在使用數據庫. 這種由於路徑等所有內容都完全一樣, 所以, 直接exp, imp就可以了, (這種使用full是比較合適的)

2. 目標與源數據庫環境不一樣, 這時, 就不能隨便讓imp自動創建表空間, 因為創建的路徑有問題, 這個時候,做法是:  - 首先查看源數據庫的用戶和默認表空間:    select name from v$tablespace;    select username,default_tablespace from dba_users;  - 然后, 在目標數據庫上考量好, 應該對應以上用戶建立哪些表空間和用戶: (注意: 導入時, 不要帶索引, 要重建索引)    創建對應用戶, 並給用戶賦予默認表空間    給予這些新建的用戶權限, 並同時收回創建表空間權限(否則 imp 還是會自動為這些用戶創建自動表空間)    grant connect,resource,dba to test;    revoke unlimited tablespace from username;

exp system/manager@TEST file=d:\daochu.dmp tables=(table1) query=\" where filed1 like '00%'\"

經常有人會問:原來的數據在USERS表空間里面,我想把它IMP進APP表空間,我已經修改了目的用戶的默認表空間,為什么結果還是IMP到USERS表空間中了呢。

關於此問題,作如下解釋:   Oracle並沒有提供什么參數來指定要導入哪個表空間,數據默認將導入到原本導出時數據所在的表空間中,但是我們可以通過以下的方法來實現導入到不同的表空間。

1.在IMP時候使用INDEXFILE參數   當給此參數指定了某一文件名,IMP的時候所有的index將不會直接導入到表空間中,而是在指定的文件中生成創建index的腳本。   然后用文本編輯器打開此文件,直接編輯腳本中的storage參數,修改為想要導入的表空間名稱。

然后重新執行IMP,使用INDEXS=n參數將除Index之外的Objects導入。   最后進入SQL*PLUS,直接運行剛才編輯的腳本,生成索引。

該方法適用於將index以及constraints導入指定的表空間。

2.改變目的用戶的默認表空間

這就是上面說的經常有人提問的方法。但是上述的問題之所以沒有成功,是因為缺少了下面的幾步。

首先,收回目的用戶的”UNLIMITED TABLESPACE”權限:

revoke unlimited tablespace from username; 其次,取消目的用戶在原數據導出表空間中的配額,這樣才能迫使IMP把數據導入到用戶的默認表空間中去。 然后,將希望導入的表空間設為目的用戶的默認表空間,並添加配額。 最后,執行IMP。

、帶有查詢語句的導出  exp file=filename.dmp triggers=n full=n tables=table_name query=\"where rownum \<10000\"  (其中query后面的非數字字母字符均需要轉義字符\,引號用"")

、標准的導出語句 exp userid/password tables=table_name file=filename.dmp

二. 用戶模式 這種模式雖然不會創建表空間, 而在創建table的時候, 會指定物理的表空間位置, 換句話說, 如果在目標數據庫中沒有以前這個表的表空間存在, 那么就會放到默認表空間, 否則會放到與之前一樣的表空間. 表模式, 個人感覺應該跟這個差不多.

最后, 個人覺得, 跨平台, 最好還是使用用戶模式.

只有完全相同的數據庫之間, 推薦使用 full 模式.

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM