Mit Datapump bietet Oracle ab Version 10 eine Weiterentwicklung und Ersatz der export/import Funktionalität an. Dabei bietet Datapump gegenüber dem alten export/import Tool erhebliche Vorteile.
Das mit Version 10 neu ausgelieferte Datapump-Utility gegenüber dem alten export/import Tool erhebliche Vorteile. Die wichtigsten Features sind:
Das Schreiben der Export-Files erfolgt in ein Oracle-Directory auf dem Server. Dies ist bei RAC-Systemen zu beachten. Somit können die Export (Dump) Files nicht mehr über eine SQLNET-Verbindung von einem externen Server gelesen bzw geschrieben werden. Dies ist der parallelen Verarbeitung und dem deutlichen Zugewinn im Durchsatz geschuldet, kann aber in bestimten Umgebungen problematisch sein.
Zentrale Einheit jeder Data Pump Operation ist die Master Tabelle. Sie wird im Schema des Benutzers erstellt, der den Data Pump Job aufruft. Sie enthält alle Informationen über den Job:
Die Master Tabelle wird während des Exports und Imports erstellt und ist mit untem stehendenfolgendem SQL zu finden.
SELECT o.status, o.object_id, o.object_type, o.owner||'.'||object_name master_table_name FROM dba_objects o, dba_datapump_jobs j WHERE o.owner=j.owner_name AND o.object_name=j.job_name ;
Anhand der Master Tabelle kann der aktuelle Status beim Import/Export schnell verifiziert werden, inbesondere Informationen zum meist zeitintensiven Datenexport/Import sind so schnell verfügbar.
select * from master_table_name where job_name = 'MY_EXPORT_JOB' and object_type = 'TABLE_DATA'
Dieser ruft die Data Pump API auf. Die neuen Clients expdp und impdp besitzen neben der bereits in exp und imp enthaltenen Funktionalität zusätzlich eine Reihe von weiteren Features.
Dies ist ein Dedicated Server Prozess der gestartet wird sobald sich ein Client sich mit der Datenbank verbindet. Nach einem Aufruf von DBMS_DATAPUMP.OPEN startet der Server Prozess den eigentlichen Job anzustoßen und generiert die Master Table.
Pro Job existiert immer nur ein MCP (Master Control Prozess). Dieser kontrolliert die Abarbeitung und Verteilung eines Data Pump Jobs. Der MCP ist unter anderem für folgedes zuständig:
DBMS_DATAPUMP.SET_PARALLEL( handle => h, degree => Anzahl_Paralleler_Prozesse ); .definiert.
Hier betrachten wir nur die Steuerung des Datapumps über die PL/SQL API. Somit ist man nicht auf das Vorhandensein der Clients Tools angewiesen und kann eigene PL/SQL Blöcke mit zusätzlichen Funktionalitäten entwicken.
Mit Hilfe der Datapump-Api kann über einen DB Link ganze Schemas oder auch nur einzelne Objekte kopiert werden. Wird ein loopback link verwendet kann man so ein Schema in einer DB elegant duplizieren. Im ersten Schritt wird Data Pump initialisiert:
create database link my_db_link ... SET SERVEROUTPUT ON SIZE 1000000 DECLARE dump_handle NUMBER; l_last_job_state VARCHAR2(30) := 'UNDEFINED'; l_job_state VARCHAR2(30) := 'UNDEFINED'; l_sts KU$_STATUS; scn_number number; BEGIN dump_handle := DBMS_DATAPUMP.open( operation => 'IMPORT', job_mode => 'SCHEMA', remote_link => 'my_db_link', job_name => 'MY_PUMP_JOB', version => 'LATEST'); dbms_output.put_line(dump_handle);
Nach dem Öffnen des Data Pumps können einzelne Optionen definiert werden:
scn_number := dbms_flashback.get_system_change_number@my_db_link ; dbms_datapump.set_parameter(h, 'FLASHBACK_SCN', scn_number); dbms_output.put_line(scn_number); .
DBMS_DATAPUMP.metadata_filter( handle => h, name => 'SCHEMA_EXPR', value => '= ''SCHEMA1'''); .oder
DBMS_DATAPUMP.metadata_filter( handle => dump_handle, name => 'SCHEMA_EXPR', value => 'in (''SCHEMA1'',''SCHEMA2'')'); .und für einzelne Tabellennamen:
dbms_datapump.metadata_filter(handle => dump_handle, ´ name => 'NAME_EXPR', value => 'IN (''TABLE_NAME'')'); .
DBMS_DATAPUMP.SET_PARALLEL( handle => dump_handle, degree => 5); .
dbms_datapump.metadata_remap(dump_handle,'REMAP_SCHEMA','SCHEMA1','SCHEMA3'); Als Parameter sind folgende Keywords zulässig: REMAP_TABLESPACE REMAP_SCHEMA REMAP_DATAFILESollen mehrere Tablespaces geändert werden kann dies wie folgt realisiert werden
define type tbsp_type is table of varchar2(128); v_ar_remap_tbsp_rule tbsp_type := tbsp_type('TBSP_OLD_1:TBSP_NEW_1','TBSP_OLD_2:TBSP_NEW_2'); i number; begin IF v_ar_remap_tbsp_rule.COUNT > 0 THEN FOR i IN 1 .. v_ar_remap_tbsp_rule.COUNT LOOP DBMS_DATAPUMP.METADATA_REMAP ( handle => h, name => 'REMAP_TABLESPACE', old_value => substr(v_ar_remap_tbsp_rule(i),1,instr(v_ar_remap_tbsp_rule(i),':') -1 ), value => substr(v_ar_remap_tbsp_rule(i),instr(v_ar_remap_tbsp_rule(i),':') +1 ,length(v_ar_remap_tbsp_rule(i)) ) ); END LOOP; END IF; end;
dbms_datapump.set_parameter (h, 'TABLE_EXISTS_ACTION', 'APPEND'); -- oder dbms_datapump.set_parameter (h, 'TABLE_EXISTS_ACTION', 'REPLACE'); .
DBMS_DATAPUMP.set_parameter (handle => h, name => 'KEEP_MASTER', VALUE => 1); .Die Tabellen sollten zu einem späteren Zeitpunkt manuell gelöscht werden.
Nach Setzung aller notwendigen Parameter kann der Job gestartet werden:
DBMS_DATAPUMP.start_job(dump_handle); .
Das Monitoring des Jobs erfolgt am einfachsten über die Mastertabelle:
select * from master_table_name where job_name = 'MY_EXPORT_JOB' and object_type = 'TABLE_DATA' ;
Hierfür muß im ersten Schritt ein Oracle Directory angelegt werden. Wie bereits erwähnt ist bei Systemen mit mehr als einem Knoten dieses Directory mit Bedacht zu wählen. Der Dumpfile selber wird vom Oracle nicht mit einem globalen Read-Privileg (chmod o+r) ausgestattet, der Logfile bekommt ein solches globales Read-Privilege.
create directory MY_DUMP_DIR as '/opt/app/oracle/something_shared' grant READ, WRITE on directory MY_DUMP_DIR to operation_user; .
Anschließend erfolgt der Export über das bereits im obigen Beispiel diskutierte Vorgehen:
DECLARE dump_handle NUMBER; BEGIN dump_handle := DBMS_DATAPUMP.open( operation => 'EXPORT', job_mode => 'SCHEMA', remote_link => NULL, job_name => 'MY_PUMP_JOB', version => 'LATEST');
Da diesmal kein DB Link verwendet wird müssen die Dump- und Logfiles explizit angelegt werden.
DBMS_DATAPUMP.add_file( handle => dump_handle, filename => 'MY_DUMP_FILE.dmp', directory => 'MY_DUMP_DIR'); DBMS_DATAPUMP.add_file( handle => dump_handle, filename => 'MY_DUMP_FILE.log', directory => 'MY_DUMP_DIR', filetype => DBMS_DATAPUMP.KU$_FILE_TYPE_LOG_FILE); DBMS_DATAPUMP.metadata_filter( handle => dump_handle, name => 'SCHEMA_EXPR', value => '= ''SCHEMA1''');
Da man es gerne schnell hat kann bei größeren Schemas und Tabellen wieder eine parallele Verarbeitung vorgesehen werden:
DBMS_DATAPUMP.SET_PARALLEL( handle => dump_handle, degree => 5); .
Anschließend muß der Job nur noch gestartet werden
DBMS_DATAPUMP.start_job(l_dp_handle); .
Hierdurch können Stukturexporte / Importe erstellt werden. Das Vorgehen entspricht wieder dem aus obigen Beispiel. Diesmal wird ein Datenfilter mit ROWS=0 hinzugefügt.
DECLARE dump_handle NUMBER; BEGIN dump_handle := DBMS_DATAPUMP.open( operation => 'EXPORT', job_mode => 'SCHEMA', remote_link => NULL, job_name => 'MY_PUMP_JOB', version => 'LATEST'); DBMS_DATAPUMP.add_file( handle => dump_handle, filename => 'MY_DUMP_FILE_STRUCTURE.dmp', directory => 'MY_DUMP_DIR'); DBMS_DATAPUMP.add_file( handle => dump_handle, filename => 'MY_DUMP_FILE_STRUCTURE.log', directory => 'MY_DUMP_DIR', filetype => DBMS_DATAPUMP.KU$_FILE_TYPE_LOG_FILE); DBMS_DATAPUMP.metadata_filter( handle => dump_handle, name => 'SCHEMA_EXPR', value => '= ''SCHEMA1'''); DBMS_DATAPUMP.data_filter( handle=> dump_handle, name=> 'INCLUDE_ROWS' , value=>0): DBMS_DATAPUMP.start_job(l_dp_handle);
Bricht ein Export / Import ab und wird beendet kann der Job selber gelöscht sein, man findet aber immer noch Einträge im view dba_datapump_jobs. In diesen Fällen konnte beim Abbruch die Master-Tabelle nicht gelöscht werden. Diese kann problemlos manuell gelöscht werden:
SELECT 'drop table o.owner||'.'||object_name ||';' drop_stmt FROM dba_objects a, dba_datapump_jobs b WHERE a.owner=b.owner_name AND a.object_name=b.job_name ;