您好,登錄后才能下訂單哦!
原文: https://www.enmotech.com/web/detail/1/788/1.html
導(dǎo)讀:本文來自讀者“小豹子加油(網(wǎng)名)”的投稿,主要講述使用imp導(dǎo)入文件出現(xiàn)IMP-00009問題的處理過程。
一、概述
最近在測試環(huán)境的一個Oracle數(shù)據(jù)庫上面,使用exp將表導(dǎo)出沒有問題,而將導(dǎo)出的文件使用imp導(dǎo)入時卻出現(xiàn)了如下錯誤。
IMP-00009: abnormal end of export file
Import terminated successfully with warnings.
經(jīng)過反復(fù)實驗,終于找出問題出現(xiàn)的原因,是由以下幾點共同造成的:
a. 數(shù)據(jù)庫中參數(shù)deferred_segment_creation設(shè)置的是默認(rèn)值true,即創(chuàng)建表的時候不立即分配段,等有行的時候才會分配段。
b. 導(dǎo)出的表中有分區(qū)表,而恰好該分區(qū)表存在分區(qū)沒有行的情況,即有的分區(qū)沒有分配段。
c. 導(dǎo)出時使用了direct=true。
解決辦法直接看(三、解決辦法)
二、問題復(fù)現(xiàn)
1. 準(zhǔn)備工作
在測試庫中準(zhǔn)備兩個用戶,tom(導(dǎo)出的用戶),jerry(導(dǎo)入的用戶),分別給予其最大的權(quán)限。
SQL> create user tom identified by tom;
SQL> grant dba to tom;
SQL> create user jerry identified by jerry;
SQL> grant dba to jerry;
2. 檢查數(shù)據(jù)庫中參數(shù)deferred_segment_creation
SQL> show parameter deferred
NAME TYPE VALUE
------------------------------------ ----------- ------------------------------
deferred_segment_creation boolean TRUE
可以看到該參數(shù)是true,默認(rèn)值。
3. 創(chuàng)建測試表
SQL> create table tom.t_normal as select * from scott.emp; // 創(chuàng)建一張普通表,并且有行
SQL> create table tom.t_norows as select * from scott.emp where 1=0; // 創(chuàng)建一張空表
SQL> create table tom.t_par(id number, name varchar2(10))
partition by list(id)
(partition p01 values(1),
partition p02 values(default)); // 創(chuàng)建一張分區(qū)表,兩個分區(qū)
SQL> insert into tom.t_par values(1, 'aa'); // 往分區(qū)p01插入一條數(shù)據(jù)
SQL> commit;
至此,tom用戶下有三張表,t_normal是普通表,t_norows是一張普通的空表,t_par是分區(qū)表。
通過下面的sql查到tom用戶下只有兩個segment,空表和分區(qū)表中無數(shù)據(jù)的分區(qū)都沒有創(chuàng)建段。
SQL> select owner,segment_name,partition_name,segment_type from dba_segments where owner='TOM';
OWNER SEGMENT_NAME PARTITION_NAME SEGMENT_TYPE
---------- -------------------- ------------------------------ ------------------
TOM T_NORMAL TABLE
TOM T_PAR P01 TABLE PARTITION
4. 使用tom對表進(jìn)行導(dǎo)出
exp tom/tom file=tom.dmp log=tom_exp.log direct=true
導(dǎo)出日志如下(省略部分無關(guān)內(nèi)容):
. . exporting table T_NORMAL 14 rows exported
. . exporting table T_NOROWS 0 rows exported
. . exporting table T_PAR
. . exporting partition P01 1 rows exported
. . exporting partition P02 0 rows exported
Export terminated successfully without warnings.
5. 使用jerry對文件進(jìn)行導(dǎo)入
mp jerry/jerry file=tom.dmp log=jerry_imp.log fromuser=tom touser=jerry
導(dǎo)入日志如下(省略部分無關(guān)內(nèi)容):
. . importing table "T_NORMAL" 14 rows imported
. . importing table "T_NOROWS" 0 rows imported
. . importing partition "T_PAR":"P01" 1 rows imported
. . importing partition "T_PAR":"P02"
IMP-00009: abnormal end of export file
Import terminated successfully with warnings.
生產(chǎn)上面出現(xiàn)的錯誤在這里就得到復(fù)現(xiàn)了。而且是在導(dǎo)入"T_PAR":"P02"出現(xiàn)的錯誤,這個正好印證了前面的觀點。
三、解決辦法
解決辦法有以下兩種(任一即可):
a. 使用exp導(dǎo)出的時候不要加direct=true
b. 設(shè)置數(shù)據(jù)庫的參數(shù)deferred_segment_creation為false(注意:這個參數(shù)只影響新建的分區(qū)表,老的分區(qū)表導(dǎo)出再導(dǎo)入仍然會報錯!)
四、有時間、有興趣的讀者可以接著做實驗
可能大家會問,你怎么知道是分區(qū)表的問題,又怎么知道是direct=true的問題,又怎么知道是參數(shù)deferred_segment_creation的問題?接下來我一一驗證。
1. 清空jerry的表,導(dǎo)出tom用戶下表t_normal,t_norows,再導(dǎo)入到j(luò)erry用戶中
SQL> drop user jerry cascade; // 通過重建jerry用戶來清空jerry的表
SQL> create user jerry identified by jerry;
SQL> grant dba to jerry;
exp tom/tom file=tom.dmp log=tom_exp.log direct=true tables=t_normal,t_norows
導(dǎo)出日志:
. . exporting table T_NORMAL 14 rows exported
. . exporting table T_NOROWS 0 rows exported
Export terminated successfully without warnings.
imp jerry/jerry file=tom.dmp log=jerry_imp.log fromuser=tom touser=jerry
導(dǎo)入日志:
. . importing table "T_NORMAL" 14 rows imported
. . importing table "T_NOROWS" 0 rows imported
Import terminated successfully without warnings.
可以看到對這兩張表導(dǎo)入是沒有問題的
2. 清空jerry的表,導(dǎo)出tom用戶下表t_par,再導(dǎo)入到j(luò)erry用戶中
清空jerry的表的操作請看上面的步驟
exp tom/tom file=tom.dmp log=tom_exp.log direct=true tables=t_par
導(dǎo)出日志:
. . exporting table T_PAR
. . exporting partition P01 1 rows exported
. . exporting partition P02 0 rows exported
Export terminated successfully without warnings.imp jerry/jerry file=tom.dmp log=jerry_imp.log fromuser=tom touser=jerry
導(dǎo)入日志:
. importing TOM's objects into JERRY
. . importing partition "T_PAR":"P01" 1 rows imported
. . importing partition "T_PAR":"P02"
IMP-00009: abnormal end of export file
Import terminated successfully with warnings.
可以看到問題就出在對這張分區(qū)表的導(dǎo)入上面了
3. 清空jerry的表,重新導(dǎo)出tom用戶下表t_par,再導(dǎo)入到j(luò)erry用戶中(這次導(dǎo)出不加參數(shù)direct=true)
清空jerry的表的操作請看上面的步驟
exp tom/tom file=tom.dmp log=tom_exp.log tables=t_par
導(dǎo)出日志:
. . exporting table T_PAR
. . exporting partition P01 1 rows exported
. . exporting partition P02 0 rows exported
Export terminated successfully without warnings.imp jerry/jerry file=tom.dmp log=jerry_imp.log fromuser=tom touser=jerry
導(dǎo)入日志:
. importing TOM's objects into JERRY
. . importing partition "T_PAR":"P01" 1 rows imported
. . importing partition "T_PAR":"P02" 0 rows imported
Import terminated successfully without warnings.
可以看到這次導(dǎo)入沒有任何問題,也就是說不加direct=true直接可以解決問題,但是如果我非要加這個參數(shù)呢,或者說這個命令寫死到程序中了,沒辦法改怎么辦?處理辦法看下面第6條。
4. 清空jerry的表,在tom.t_par的p02分區(qū)中插入一條數(shù)據(jù),重新導(dǎo)出tom用戶下表t_par,再導(dǎo)入到j(luò)erry用戶中(這次導(dǎo)出依然加參數(shù)direct=true)
清空jerry的表的操作請看上面的步驟
SQL> insert into tom.t_par values(2, 'bb'); // 往分區(qū)p02插入一條數(shù)據(jù)SQL> commit;
通過下面的sql查到t_par兩個分區(qū)都有段了
SQL> select owner,segment_name,partition_name,segment_type from dba_segments where owner='TOM';
OWNER SEGMENT_NAME PARTITION_NAME SEGMENT_TYPE
---------- -------------------- ------------------------------ ------------------
TOM T_PAR P01 TABLE PARTITION
TOM T_PAR P02 TABLE PARTITION
TOM T_NORMAL TABLE
exp tom/tom file=tom.dmp log=tom_exp.log direct=true tables=t_par
導(dǎo)出日志:
. . exporting table T_PAR. . exporting partition P01 1 rows exported
. . exporting partition P02 1 rows exported
Export terminated successfully without warnings.
imp jerry/jerry file=tom.dmp log=jerry_imp.log fromuser=tom touser=jerry
導(dǎo)入日志:
. importing TOM's objects into JERRY
. . importing partition "T_PAR":"P01" 1 rows imported
. . importing partition "T_PAR":"P02" 1 rows imported
Import terminated successfully without warnings.
可以看到分區(qū)表中所有分區(qū)都有數(shù)據(jù)的話,導(dǎo)入就沒有任何問題
5. 驗證deferred_segment_creation參數(shù)對其的影響
清空jerry的表的操作請看上面的步驟
修改數(shù)據(jù)庫中參數(shù)deferred_segment_creation為false
SQL> alter system set deferred_segment_creation=false;
重建tom用戶的t_par表,讓其一個分區(qū)有數(shù)據(jù),另外一個分區(qū)無數(shù)據(jù)
SQL> drop table tom.t_par;
SQL> create table tom.t_par(id number, name varchar2(10))
partition by list(id)
(partition p01 values(1),
partition p02 values(default)); // 創(chuàng)建一張分區(qū)表,兩個分區(qū)
SQL> insert into tom.t_par values(1, 'aa'); // 往分區(qū)p01插入一條數(shù)據(jù)
SQL> commit;
通過下面的sql查到t_par兩個分區(qū)都有段了,即使p02分區(qū)里面沒有數(shù)據(jù)
SQL> select owner,segment_name,partition_name,segment_type from dba_segments where owner='TOM';OWNER SEGMENT_NAME PARTITION_NAME SEGMENT_TYPE
---------- -------------------- ------------------------------ ------------------
TOM T_PAR P01 TABLE PARTITION
TOM T_PAR P02 TABLE PARTITION
TOM T_NORMAL TABLE
exp tom/tom file=tom.dmp log=tom_exp.log direct=true tables=t_par
. . exporting table T_PAR
. . exporting partition P01 1 rows exported
. . exporting partition P02 0 rows exported
Export terminated successfully without warnings.
imp jerry/jerry file=tom.dmp log=jerry_imp.log fromuser=tom touser=jerry
導(dǎo)入日志:
. importing TOM's objects into JERRY
. . importing partition "T_PAR":"P01" 1 rows imported
. . importing partition "T_PAR":"P02" 0 rows imported
Import terminated successfully without warnings.
可以看到將參數(shù)deferred_segment_creation修改為false導(dǎo)入也正常,但是這只適用于新建的分區(qū)表,對于已經(jīng)存在的分區(qū)表,依然會導(dǎo)入失敗。處理辦法看下面第6條。
6. 接下來回答上面第3和5步中的問題
如果想用exp,imp進(jìn)行導(dǎo)出導(dǎo)入,導(dǎo)出的時候又必須加direct=true,而且導(dǎo)出的表中包含分區(qū)表,并且該分區(qū)表中存在分區(qū)沒有段的情況。那怎么辦?
光是將參數(shù)deferred_segment_creation修改為false不夠,因為這只影響新建的表,要想對老的表也生效,可以采取下面的辦法。
6.1. 將參數(shù)deferred_segment_creation修改為false
SQL> alter system set deferred_segment_creation=false;
6.2. 使用exp對分區(qū)表進(jìn)行導(dǎo)出(只有那些分區(qū)表中存在分區(qū)沒有分配段的才需要導(dǎo)出),注意不要加direct=true
exp tom/tom file=tom.dmp log=tom_exp.log tables=t_par
6.3. 刪除該分區(qū)表
SQL> drop table tom.t_par;
6.4. 使用imp對其進(jìn)行導(dǎo)入
imp tom/tom file=tom.dmp log=tom_imp.log full=y
導(dǎo)入日志
. importing TOM's objects into TOM
. . importing partition "T_PAR":"P01" 1 rows imported
. . importing partition "T_PAR":"P02" 0 rows imported
Import terminated successfully without warnings.
導(dǎo)入后查看段的情況
SQL> select owner,segment_name,partition_name,segment_type from dba_segments where owner='TOM';
OWNER SEGMENT_NAME PARTITION_NAME SEGMENT_TYPE
---------- -------------------- ------------------------------ ------------------
TOM T_PAR P02 TABLE PARTITION
TOM T_PAR P01 TABLE PARTITION
可以看到現(xiàn)在即使P02分區(qū)中沒有行,也分配了段。這是由于我先前已經(jīng)將參數(shù)deferred_segment_creation設(shè)置成了false,并且刪除了表,imp在執(zhí)行過程中,會先創(chuàng)建表然后插入數(shù)據(jù),在創(chuàng)建表時,每個分區(qū)都會分配段。也就是說只需要解決老的分區(qū)表中段沒有分配的情況,后面就不會碰到IMP-00009。
五、總結(jié)
只有在分區(qū)表中存在分區(qū)沒有分配段,而且在導(dǎo)出時使用了direct=true參數(shù),這兩種情況在一起才會造成我這個IMP-00009這個錯誤。對于其它的普通表,不管有沒有分配段,是否使用direct=true都不會造成這個錯誤。
我在分析IMP-00009這個問題的時候,首先日志紀(jì)錄只有一行,就寫"IMP-00009: abnormal end of export file",第一時間去查導(dǎo)出的日志,"Export terminated successfully without warnings.",導(dǎo)出的日志沒有顯示任何異常。這就把我整懵逼了。然后我開始求助于萬能的互聯(lián)網(wǎng),查了一圈下來,沒有找到任何解決方案,其實不是大牛不解答,而是問問題的人提供的信息太少了,你就提供個錯誤日志,比方說我這次碰到的問題,假設(shè)你只給個錯誤日志,大牛打死也復(fù)現(xiàn)不出來問題,那就談不上去解決問題了。而往往當(dāng)我們把整個問題都描述清楚了,問題大概率就迎刃而解了。
文章中涉及到的相關(guān)信息備注:
deferred_segment_creation:延遲段創(chuàng)建,上面已經(jīng)通過實驗介紹的很清楚了。
direct=true:導(dǎo)出數(shù)據(jù)時不經(jīng)過buffer cache,這個參數(shù)是個天坑,bug極多,導(dǎo)出時盡量不要用。
出處:https://www.cnblogs.com/ddzj01/
想了解更多關(guān)于數(shù)據(jù)庫、云技術(shù)的內(nèi)容嗎?
快來關(guān)注“數(shù)據(jù)和云”公眾號、“云和恩墨”官方網(wǎng)站,我們期待與大家一同學(xué)習(xí)和進(jìn)步!
(掃描上方二維碼,關(guān)注“數(shù)據(jù)和云”公眾號,即可查看更多科技文章)
免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點不代表本網(wǎng)站立場,如果涉及侵權(quán)請聯(lián)系站長郵箱:is@yisu.com進(jìn)行舉報,并提供相關(guān)證據(jù),一經(jīng)查實,將立刻刪除涉嫌侵權(quán)內(nèi)容。