[英]Error while importing oracle dump using DBMS_DATAPUMP in oracle 12g
[英]How do you make DBMS_DATAPUMP error if there's an error?
當源表和目標表中的列不匹配時,DBMS_DATAPUMP不會失敗。 這意味着不會引發任何異常。 我正在嘗試使用GET_STATUS程序,以了解是否有任何錯誤,但遺憾的是似乎沒有......
我的最終目標是DBMS_DATAPUMP在導入失敗時引發異常。 不同的列是一個簡單的例子,因為我知道它應該失敗。
這是我當前的代碼(我故意模糊了模式名稱)。 我正在使用的環境在兩台服務器上是相同的,除了我已經在源表中添加了一個額外的列。 我還執行表中行數的計數。
connect schema/*@db1/db1
-- */
create table tmp_test_datapump as
select u.*, cast(null as number) as break_it
from user_tables u;
Table created.
select count(*) from tmp_test_datapump;
COUNT(*)
----------
1170
connect schema/*@db2/db2
-- */
set serveroutput on
create table tmp_test_datapump as
select u.*
from user_tables u;
Table created.
在嘗試測試時,DATAPUMP代碼有點復雜。 可以刪除無限循環中的所有內容,這將起到相同的作用。
declare
l_handle number;
l_status varchar2(255);
l_job_state varchar2(4000);
l_ku$status ku$_status1020;
begin
l_handle := dbms_datapump.open( operation => 'IMPORT'
, job_mode => 'TABLE'
, remote_link => 'SCHEMA.DB.DOMAIN.COM'
, job_name => 'JOB_TEST_DP'
, version => 'COMPATIBLE' );
dbms_datapump.set_parameter( handle => l_handle
, name => 'TABLE_EXISTS_ACTION'
, value => 'TRUNCATE');
dbms_datapump.metadata_filter( handle => l_handle
, name => 'NAME_EXPR'
, value => 'IN (''TMP_TEST_DATAPUMP'')');
dbms_datapump.start_job(handle => l_handle);
while true loop
dbms_datapump.wait_for_job(handle => l_handle,job_state => l_status);
if l_status in ('COMPLETED','STOPPED') then
exit;
end if;
dbms_datapump.get_status( handle => l_handle
, mask => dbms_datapump.KU$_STATUS_JOB_ERROR
, job_state => l_job_state
, status => l_ku$status);
dbms_output.put_line('state: ' || l_job_state);
if l_ku$status.error is not null and l_ku$status.error.count > 0 then
for i in l_ku$status.error.first .. l_ku$status.error.last loop
dbms_output.put_line(l_ku$status.error(i).logtext);
end loop;
end if;
end loop;
end;
/
PL/SQL procedure successfully completed.
select count(*) from tmp_test_datapump;
COUNT(*)
----------
47
如您所見,表中的記錄數量不同; 導入失敗,沒有例外。 各種 博客和DBA.SE問題意味着可以進行某種錯誤捕獲; 但我似乎無法管理它。
如何在DBMS_DATAPUMP導入中捕獲致命錯誤?
我正在使用dbms_datapump
包知道。 以下過程在一個表中搜索將要導出的模式。 BACKUP_INFO_MOD
是一個PRAGMA AUTONOMOUS TRANSACTION
的程序,它在另一個表中創建日志。
本文檔中的示例6.3對我幫助很大。 這是我的代碼中的片段(附加注釋):
CREATE OR REPLACE PROCEDURE BACKUP_EXECUTE (
threads in number := 1
, dir in varchar2 := 'DATA_PUMP_DIR'
) AS
schemas varchar2(255);
filename varchar2(255);
path varchar2(255);
errormsg varchar2(4000);
handle number;
job_state varchar2(30);
--variables under this line are important to error handling
logs ku$_LogEntry;
lindx pls_integer;
status ku$_Status;
exporterr exception; --our exception to handle export errors
[...]
BEGIN
[...]
schemas:=schema_list(indx).schema_name;
--Full dir path for logs
select directory_path into path from dba_directories where directory_name=dir;
--If data not found then automatically raise NO_DATA_FOUND
select to_char(sysdate, 'YYMMDDHH24MI-')||lower(schemas)||'.dmp' into filename from dual;
backup_info_mod('insert',path||filename,schemas);
begin --For inner exception handling on short fragment
handle := dbms_datapump.open('EXPORT','SCHEMA');
dbms_datapump.add_file(handle, filename, dir); --dump file
dbms_datapump.add_file(handle, filename||'.log', dir,null,DBMS_DATAPUMP.KU$_FILE_TYPE_LOG_FILE); --export log file
dbms_datapump.metadata_filter(handle, 'SCHEMA_EXPR', 'IN ('''||schemas||''')');
dbms_datapump.set_parallel(handle,threads);
backup_info_mod(file_name=>path||filename, curr_status=>'IN PROGRESS');
dbms_datapump.start_job(handle);
--If job didn't start due to some errors, then let's get some information
exception
when others then
dbms_datapump.get_status(handle,8,0,job_state,status);
--This will overwrite our job_state and status
end;
--Let's go handle error if job_state was overwritten
if job_state is not null then
raise exporterr;
else
job_state:='UNDEFINED';
end if;
--Checking in loop if errors occurred. I'm not using wait_for_job
--because it didn't work out
while (job_state != 'COMPLETED') and (job_state != 'STOPPED') loop
--Like before, let's get some information
dbms_datapump.get_status(handle,8,-1,job_state,status);
--Looking for errors using mask
if (bitand(status.mask,dbms_datapump.ku$_status_job_error) != 0) then
--If occurred: let's stop the export job and raise an error
dbms_datapump.stop_job(handle);
dbms_datapump.detach(handle);
raise exporterr;
exit;
end if;
end loop;
backup_info_mod(file_name=>path||filename, curr_status=>'COMPLETED');
dbms_datapump.detach(handle);
exception
when NO_DATA_FOUND then
backup_info_mod('insert',null,schemas,'ERROR','No '||dir||' defined in dba_directories');
when exporterr then
--Let's get all error messages and write it to errormsg variable
logs:=status.error;
lindx:=logs.FIRST;
while lindx is not null loop
errormsg:=errormsg||logs(lindx).LogText;
lindx:=logs.NEXT(lindx);
if lindx is not null then
errormsg:=errormsg||' | '; --Just to separate error messages
end if;
end loop;
backup_info_mod(
file_name=>path||filename,
curr_status=>'ERROR',
errormsg=>errormsg);
/*when other then --TODO
null;
*/
end;
END BACKUP_EXECUTE;
在為impdp創建日志時,可以將datapump命令放在shell腳本中,在結束shell腳本之前,可以檢查日志中的IMP-錯誤或ORA-錯誤,如果為true則警告用戶查看日志文件錯誤。
yammy提供的文件很好。
使用dbms_datapump包導入數據庫轉儲時遇到了同樣的問題。 即使導入期間出錯,該作業也會被視為成功/完成。 通過使用文檔中的代碼示例,我可以在導入期間獲取錯誤/日志消息。 然后檢查日志消息中是否找到“ORA-”並在導入作業完成時拋出自定義錯誤。
以下是示例代碼:
PROMPT CREATE OR REPLACE PROCEDURE import_schema
CREATE OR REPLACE PROCEDURE import_db_dump (
dumpFilename IN VARCHAR2)
IS
handle NUMBER; -- Handler of the job
loopIdx NUMBER; -- Loop index
percentDone NUMBER; -- Percentage of job complete
jobState VARCHAR2(30); -- To keep track of job state
ku_logEntry ku$_LogEntry; -- For WIP and error messages
ku_jobStatus ku$_JobStatus; -- The job status from get_status
ku_jobDescjd ku$_JobDesc; -- The job description from get_status
ku_Status ku$_Status; -- The status object returned by get_status
errorCount NUMBER;
import_error_found EXCEPTION;
BEGIN
handle := dbms_datapump.open (
operation => 'IMPORT',
job_mode => 'SCHEMA');
dbms_output.put_line('Define table exists action: truncate');
dbms_datapump.set_parameter (
handle => handle,
name => 'TABLE_EXISTS_ACTION',
value => 'TRUNCATE');
dbms_output.put_line('Define dumpfilename: ' || dumpFilename);
dbms_datapump.add_file (
handle => handle,
filename => dumpFilename,
filetype => dbms_datapump.ku$_file_type_dump_file);
dbms_output.put_line('Start datapump job');
dbms_output.put_line('==================');
dbms_datapump.start_job (handle);
-- Ref: http://docs.oracle.com/cd/E11882_01/server.112/e22490/dp_api.htm#SUTIL977
-- The import job should now be running. In the following loop, the job is
-- monitored until it completes. In the meantime, progress information is
-- displayed.
percentDone := 0;
jobState := 'UNDEFINED';
errorCount := 0;
WHILE (jobState != 'COMPLETED') AND (jobState != 'STOPPED') LOOP
dbms_datapump.get_status(handle,
dbms_datapump.ku$_status_job_error +
dbms_datapump.ku$_status_job_status +
dbms_datapump.ku$_status_wip,
-1, jobState, ku_Status);
ku_jobStatus := ku_Status.job_status;
-- If the percentage done changed, display the new value.
IF ku_jobStatus.percent_done != percentDone THEN
dbms_output.put_line('*** Job percent done = ' ||
to_char(ku_jobStatus.percent_done));
percentDone := ku_jobStatus.percent_done;
END IF;
-- If any work-in-progress (WIP) or Error messages were received for the job,
-- display them.
IF (bitand(ku_Status.mask, dbms_datapump.ku$_status_wip) != 0) THEN
ku_logEntry := ku_Status.wip;
ELSE
IF (bitand(ku_Status.mask,dbms_datapump.ku$_status_job_error) != 0) THEN
ku_logEntry := ku_Status.error;
ELSE
ku_logEntry := null;
END IF;
END IF;
IF ku_logEntry IS NOT NULL THEN
loopIdx := ku_logEntry.FIRST;
WHILE loopIdx IS NOT NULL LOOP
dbms_output.put_line(ku_logEntry(loopIdx).LogText);
IF INSTR(ku_logEntry(loopIdx).LogText, 'ORA-') > 0 THEN
errorCount := errorCount + 1;
dbms_output.put_line('^^^^---ERROR FOUND');
END IF;
loopIdx := ku_logEntry.NEXT(loopIdx);
END LOOP;
END IF;
END LOOP;
-- Indicate that the job finished and gracefully detach from it.
dbms_output.put_line('Job has completed');
dbms_output.put_line('Final job state = ' || jobState);
dbms_datapump.detach(handle);
IF errorCount > 0 THEN
RAISE import_error_found;
END IF;
EXCEPTION
WHEN import_error_found THEN
dbms_output.put_line('Error found when import. Number of error: ' || errorCount);
RAISE;
WHEN OTHERS THEN
dbms_output.put_line('[Error Backtrace]');
dbms_output.put_line(dbms_utility.format_error_backtrace());
dbms_output.put_line('[Call Stack]');
dbms_output.put_line(dbms_utility.format_call_stack());
dbms_datapump.stop_job(handle);
RAISE;
END;
/
希望這有幫助。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.