Data Pump (DP) umożliwia import i eksport danych:

  • Bazy
  • Schematu
  • Tabeli
  • TABLESPACE

Procesy DP wykorzystują 2 typy plików:

  • Dane (DUMPFILE)
  • Dziennik (LOGFILE)

Żeby je tworzyć (i z nich czytać), potrzebujemy DIRECTORY na serwerze.

Let’s get to business

1. Eksport schematu

$ expdp SYSTEM/SYSTEM directory=DATA_PUMP_DIR dumpfile=hr.dmp logfile=hr_exp.log schemas=hr;
1
2
3
4
5
6
$ expdp
SYSTEM/SYSTEM
directory = DATA_PUMP_DIR
dumpfile = hr.dmp
logfile = hr_exp.log
schemas = hr
Wiersz Opis
2 Credentials, które zdecydują o zakresie akcji, które możemy wykonać.

Najprościej będzie podać dane logowania dla użytkownika z rolą DATAPUMP_EXP_FULL_DATABASE.

Pozwoli to na stworzenie DUMPFILE z metadanymi schematu. Polecam użycie credentials dla konta SYSTEM (użytkownik SYS nie posiada domyślnie wspomnianej roli).

W ramach danej bazy, użytkownik, z poziomu którego odpalę query, nie ma znaczenia. Można to łatwo sprawdzić - wykonamy akcję eksportu z poziomu nowego użytkownika z minimalną liczbą uprawnień

CREATE USER DATAPUMP_TEST IDENTIFIED BY DATAPUMP_TEST
DEFAULT TABLESPACE USERS quota unlimited ON USERS;
GRANT CREATE SESSION TO DATAPUMP_TEST;

data_pump_050.png
3 DIRECTORY, do którego użytkownik z wiersza #2 ma uprawnienia WRITE (dla eksportu) lub READ (dla importu).

OPCJONALNIE:

Sprawdzamy, jakie DIRECTORY są związane z obecnym użytkownikiem (jako owner, grantor lub grantee obiektu)

SELECT * FROM all_directories;

Sprawdzamy, jakie granty są związane z przydzieloną obecnemu użytkownikowi rolą – włączając w to rolę PUBLIC (która jest przydzielana z automatu wszystkim użytkownikom) dla danego directory – w tym przypadku dla domyślnego ‘DATA_PUMP_DIR’

SELECT * FROM all_tab_privs WHERE table_name = 'DATA_PUMP_DIR';

Jeżeli z jakiegoś powodu nie chcemy użyć domyślnego DIRECTORY, możemy stworzyć własne:

CREATE OR REPLACE DIRECTORY DATA_PUMP_TEST AS 'C:\oraclexe\app\oracle\admin\xe\DATA_PUMP_TEST';
4-5 Definiujemy nazwy DUMPFILE I LOGFILE.

LOGFILE to opcjonalny parametr.

Jeśli go nie określimy, to DP i tak stworzy plik z logiem, tyle że z domyślną nazwą - dla exportu będzie to export.log.
Jeśli wykonamy kolejną akcję exportu, to DP nie stworzy np. export2.log, tylko nadpisze export.log. Dlatego, jeśli chcemy (w przybliżeniu - zawsze chcemy) zachować log, to dobrą praktyką będzie tu zdefiniować jego nazwę.

Identycznie dla importu (domyślnie import.log).

…Gdybyśmy mimo wszystko nie potrzebowali zachowywać logu, to używamy parametru NOLOGFILE=YES Wtedy plik z logiem nie zostanie utworzony - nawet, jeśli podamy wartość parametru LOGFILE.
6 Podajemy schemat (lub schematy - np. hr,hr1…) do eksportu.

Jeśli nie mamy roli EXP_FULL_DATABASE to możemy tu podać wyłącznie własny schemat.
Jeśli ominiemy ten parametr i nie zdefiniujemy innego zakresu eksportu - np. całej bazy lub tabeli, to DP wykona swoją domyślną akcję - czyli eksport schematu, do którego podajemy credentials w wierszu #2.
Szerszy opis pod tabelą.

Ten sam user - różne dumpfile

Poniżej porównanie 2 eksportów własnego schematu przez użytkownika DATAPUMP_TEST.
Zawartość dumpfile różni się w zależności od GRANT DATAPUMP_EXP_FULL_DATABASE.

CREATE USER DATAPUMP_TEST IDENTIFIED BY DATAPUMP_TEST
DEFAULT TABLESPACE USERS quota unlimited ON USERS;
GRANT CREATE SESSION TO DATAPUMP_TEST;
GRANT CREATE TABLE TO DATAPUMP_TEST;
GRANT READ, WRITE ON DIRECTORY data_pump_dir TO DATAPUMP_TEST;
/

Bez grantu

data_pump_070.png

Z grantem

data_pump_075.png

2. Import schematu

$ impdp SYSTEM/SYSTEM directory=DATA_PUMP_DIR dumpfile=hr.dmp logfile=hr_imp.log REMAP_SCHEMA=hr:hr_copy;
1
2
3
4
5
6
$ impdp
SYSTEM/SYSTEM
directory = DATA_PUMP_DIR
dumpfile = hr.dmp
logfile = hr_imp.log
REMAP_SCHEMA = hr:hr_copy
Wiersz Opis
4 Jeśli podany DUMPFILE nie zawiera metadanych do stworzenia schematu (lub jeśli metadane są, ale USER z wiersza #2 nie ma uprawnień do ich wykorzystania), to zanim wykonamy import obiektów schematu, będziemy musieli stworzyć go (schemat) sami - a zaimportowane zostaną tylko jego obiekty.

Idąc dalej - Jeśli DUMPFILE z wiersza #4 zawiera metadane do stworzenia schematu i wskazany w wierszu #2 USER ma odpowiednie uprawnienia (DATAPUMP_IMP_FULL_DATABASE), to importowany schemat zostanie utworzony.

Jeśli użytkownik o importowanej nazwie już istnieje (w tym przypadku DATAPUMP_TEST), to program zwróci błąd. Żeby zapobiec konfilktowi nazw, użyjemy parametru REMAP_SCHEMA (wiersz #6).
6 REMAP_SCHEMA przypisuje wszystkie obiekty ze schematu źródłowego do docelowego. Jeśli schematu docelowego nie ma, to DP go utworzy (pod warunkiem wykonywania przy odpowiednich uprawnieniach).

Załóżmy, że chcemy zrobić lokalną kopię schematu DATAPUMP_TEST. Wywołajmy przy tym konfilkt nazw.

DROP USER datapump_test;

CREATE USER datapump_test IDENTIFIED BY datapump_test
DEFAULT TABLESPACE users QUOTA UNLIMITED ON users;

GRANT CREATE SESSION TO datapump_test;

$ expdp SYSTEM/SYSTEM directory=DATA_PUMP_DIR dumpfile=DATAPUMP_TEST.dmp logfile=DATAPUMP_TEST_exp.log schemas=DATAPUMP_TEST;
$ impdp SYSTEM/SYSTEM directory=DATA_PUMP_DIR dumpfile=DATAPUMP_TEST.dmp logfile=DATAPUMP_TEST_imp.log;
data_pump_060.png

Możemy wykonać kod i uniknąć błędu na 2 sposoby:
+ 1. usunąć najpierw schemat źródłowy (DATAPUMP_TEST) - wtedy import nie napotka na duplikat nazwy
2. zastosować REMAP_SCHEMA - np. REMAP_SCHEMA=DATAPUMP_TEST:DATAPUMP_TEST_COPY

Master table

Na screenie w tabeli powyżej jest informacja o Master table i obiekcie SYS_IMPORT_FULL_01.
Należy im się kilka słów opisu:

Każde uruchomienie Joba Data Pump tworzy tabelę Master table w schemacie użytkownika (wiersz #2 := SYSTEM/SYSTEM w kodzie dla Exportu i Importu), dla którego uruchamiamy polecenie.
Nazwa tej tabeli przyjmuje wartość parametru JOB_NAME.

Jeśli nie podamy JOB_NAME, to Data Pump użyje systemowo wygenerowanej nazwy - np. SYS_(EXPORT|IMPORT)_(FULL|SCHEMA)_01.

We’ve got a problem

Z automatycznie generowaną nazwą wiąże się co najmniej 1 problem.

Załóżmy, że Job nie wykona się 99 razy.
Otrzymamy wtedy np. SYS_IMPORT_FULL_99.
Kolejne nieudane wykonanie Joba zamiast SYS_IMPORT_FULL_100 wygeneruje błąd

ORA-31626: job does not exist

We’ve got a solution

Warto zdefiniować JOB_NAME z użyciem zmiennych.

Przykład dla Windows: %DATE% i %TIME%

$ impdp SYSTEM/SYSTEM directory=DATA\PUMP_DIR dumpfile=DATAPUMP_TEST.dmp logfile=DATAPUMP_TEST_imp.log
JOB_NAME=DP_IMP_%DATE%_%TIME%;

data_pump_065.png

Domyślnie Master table jest usuwana po każdym pozytywnym zakończeniu Joba. Zostaje zachowana tylko wtedy, gdy Job z jakiegoś powodu się nie wykona.

Żeby zachowywać ją niezależnie od powodzenia Joba, używamy parametru KEEP_MASTER=YES