To co najważniejsze w 10g

Jadwiga Gnybek


Miłościwie nam panująca już od jakiegoś czasu dziesiąta
wersja bazy danych Oracle jest produktem na tyle skomplikowanym, że eksploracja
coraz to nowych jej zakamarków może zająć każdą wolną chwilę administratora.

Dlatego też wciąż ukazują się kolejne opracowania wskazujące
na najważniejsze, a może tylko najciekawsze rozwiązania zastosowane w 10g.
Oczywiście mając na uwadze, że motor tej bazy kształtuje się już 27 lat, należy
przypomnieć, że nie wszystko co najlepsze w 10g wymyślono właśnie dla tej
wersji. Niektóre funkcjonalności znane były już wcześniej lub ostatnimi czasy
zyskały nowe oblicze.

Przyjrzyjmy się niektórym z nich. Dla jednych będzie to
przypomnienie mechanizmów, o których istnieniu dobrze wiedzą. Dla innych może
stanowić przewodnik po jeszcze nie odkrytych lądach.

Flashback Versions Query

Funkcjonalność ta wpisuje się świetnie w rzeczywistość, w
której obraz statyczny staje się przeżytkiem. Kamera wideo to wyposażenie niemal
standardowe nowoczesnego telefonu komórkowego czy aparatu cyfrowego. Mechanizm
taki zaimplementowany został również w odniesieniu do danych zapisanych w bazie
Oracle. Co ważne, nie jest to funkcjonalność wymagająca żmudnych konfiguracji. W
zasadzie mamy ją pod ręką zawsze, jeśli tylko o tym wiemy.

Pierwsza wersja tego mechanizmu pojawiła się już w
„dziewiątce” pod postacią Flashback Query. Administrator bazy może dzięki niej
odczytać wartość danych „archiwalnych” tak długo, jak tylko ich kopia zapisana
jest w zapisach segmentów wycofania. Ale jest to pojedynczy zestaw danych, z
którego nie możemy w żaden sposób odtworzyć dłuższej historii zmian. Potraktujmy
to zatem jako dobry początek i przyjrzyjmy się co można „wycisnąć z dziesiątki”.

Prześledźmy omawiany mechanizm na przykładzie tabeli
zawierającej kursy walut. Jak wiadomo, kursy walut zmieniają się w czasie.
Niekoniecznie chcemy zapisywać wszystkie kolejno następujące po sobie zmiany,
ale czasem warto by było odtworzyć jakieś istotne fakty z historii. Mamy więc
tablicę z dwoma kolumnami:

CURRENCY VARCHAR2
RATE NUMBER(15,10)

Powiedzmy, że wartości z tej tabeli wykorzystywane są do
przeliczeń kursów walut podczas realizacji transakcji bankowych. Jeśli z jakiś
przyczyn realizacja transakcji następuje z opóźnieniem, a nasz system zdążył już
zaktualizować kursy walut, musimy tę informację jakoś odtworzyć. Spróbujmy
przećwiczyć taki przypadek. Aplikacja dokonuje kolejnych zmian kursów walut.
Zasymulować możemy to sekwencją poleceń:

insert into rates values ("EURO",1.1012);
commit;
update rates set rate = 1.1014;
commit;
update rates set rate = 1.1013;
commit;
delete rates;
commit;
insert into rates values ("EURO",1.1016);
commit;
update rates set rate = 1.1011;
commit;

Oczywiście odpytując bazę w konwencjonalny sposób, otrzymamy
łatwą do przewidzenia odpowiedź:

SQL> select * from rates;
CURR RATE
---- ----------
EURO 1.1011

Spróbujmy jednak zapytać bazę trochę inaczej. Może pamięta
jednak coś więcej, niż ostatnią oficjalnie zakomitowaną wartość bazy:

select versions_starttime, versions_endtime, versions_xid,
versions_operation, rate
from rates versions between timestamp minvalue and maxvalue
order by VERSIONS_STARTTIME
/
VERSIONS_STARTTIME VERSIONS_ENDTIME VERSIONS_XID V RATE
------------------ ---------------- ------------ - ------
01-JAN-06 6.57.12 PM 01-JAN-06 6.57.30 PM 0002002800000C61 I 1.1012
01-JAN-06 6.57.30 PM 01-JAN-06 6.57.39 PM 000A000A00000029 U 1.1014
01-JAN-06 6.57.39 PM 01-JAN-06 6.57.55 PM 000A000B00000029 U 1.1013
01-JAN-06 6.57.55 PM 000A000C00000029 D 1.1013
01-JAN-06 6.58.07 PM 01-JAN-06 6.58.17 PM 000A000D00000029 I 1.1016
01-JAN-06 6.58.17 PM 000A000E00000029 U 1.1011

W odpowiedzi otrzymaliśmy historię zmian na tabeli. Zobaczymy
tu nawet wartości, które zostały z bazy usunięte. Jak łatwo zauważyć, jednym z
elementów informacji jest znacznik typu operacji. Mamy więc zapis mówiący, czy
zmiana na tabeli odbyła się na skutek polecenia Insert, Update czy Delete.

A wszystko to mamy – przypominam – bez konieczności
wykonywania specjalnych działań konfiguracyjnych, czy dodawania jakichkolwiek
nadmiarowych kolumn przechowujących historię albo znaczniki czasowe zmian.
Występujące w zapytaniu kolumny versions_starttime, versions_endtime,
versions_xid, versions_operation są pseudo-kolumnami takimi, jak na przykład
ROWNUM. Inne pseudo-kolumny z tej serii – takie, jak VERSIONS_STARTSCN i
VERSIONS_ENDSCN, pokazują nam System Change Numbers dla danej chwili z historii
bazy, zaś wartość z kolumny versions_xid posłużyć nam może do pozyskania
większej liczby szczegółów o danej transakcji. Musimy tylko odwołać się do
perspektywy FLASHBACK_TRANSACTION_QUERY, wstawiając wartość kolumny versions_xid
jako warunek na kolumnę XID. Dla przykładu, zapytanie takie może mieć
następującą postać:

SELECT UNDO_SQL
FROM FLASHBACK_TRANSACTION_QUERY
WHERE XID = "000A000D00000029";
UNDO_SQL
---------------------------------
insert into "ANANDA"."RATES"("CURRENCY","RATE") values ("EURO",'1.1013');

A teraz zastanówmy się, jak wykorzystać te informacje. Co
będzie, jeśli do poprawnego wykonania transakcji potrzebujemy kursów walut z
godziny – powiedzmy – 6:57:54 PM? Ot, zadajemy po prostu pytanie:

select rate, versions_starttime, versions_endtime
from rates versions
between timestamp
to_date("1/1/2006 18:57:54",'mm/dd/yyyy hh24:mi:ss')
and to_date("1/1/2006 19:57:55",'mm/dd/yyyy hh24:mi:ss')
/
RATE VERSIONS_STARTTIME VERSIONS_ENDTIME
----------------------- ----------------
1.1011

Do znalezienia potrzebnej nam wartości możemy użyć również
numerów SCN pozyskanych z pseudo-kolumn VERSIONS_STARTSCN i VERSIONS_ENDSCN.
Zapytanie miałoby wówczas postać:

select rate, versions_starttime, versions_endtime
from rates versions
between scn 1000 and 1001
/

Idąc dalej, użycie słów kluczowych MINVALUE i MAXVALUE
pozwala nam na wylistowanie wszystkich wartości zapisanych z segmentach
wycofania z dokładnością do konkretnej daty lub numeru SCN:

select versions_starttime, versions_endtime, versions_xid,
versions_operation, rate
from rates versions between timestamp
to_date("1/12/2004 15:57:52", "mm/dd/yyyy hh24:mi:ss")
and maxvalue
order by VERSIONS_STARTTIME
/
VERSIONS_STARTTIME VERSIONS_ENDTIME VERSIONS_XID V RATE
------------------ ---------------- ------------ - ------
01-DEC-03 03.57.55 PM 000A000C00000029 D 1.1013
01-DEC-03 03.58.07 PM 01-DEC-03 03.58.17 PM 000A000D00000029 I 1.1016
01-DEC-03 03.58.17 PM 000A000E00000029 U 1.1011

Jaka z tego nauka? Flashback Versions Query umożliwia
odtworzenie historii zmian danych. Nie musimy już „celować” w konkretny punkt w
czasie. Możemy przyjrzeć się historii zmian w zadanym okresie, pogłębiając jeśli
to konieczne naszą wiedzę o konkretnej wybranej operacji. Pamiętajmy jednak, że
„długość” tej pamięci zależy od wartości parametru UNDO_RETENTION.

Jak długo jeszcze, czyli ile czekać będziemy na rollback danych?

Rollback danych bywa operacją nacechowaną dużą presją czasu.
Wycofywanie transakcji, będące zwykle objawem nieprawidłowego zadziałania
systemu, bywa obarczone specjalną atencją użytkowników systemu, którzy jak nigdy
wykazują wówczas zainteresowanie pracą administratora. Wynika to często zarówno
z obawy o powodzenie operacji, jak i presji czasu związanego z realizacją
bieżących działań. W takiej sytuacji – zwłaszcza przy wycofywaniu transakcji
naprawdę dużych – warto pokusić się o estymację czasu potrzebnego na realizację
tej operacji. W Oracle 9i do odpowiedzi na to pytanie wykorzystać mogliśmy
zapytanie:

SELECT USED_UREC
FROM V$TRANSACTION;

Zwracało ono liczbę rekordów, które muszą zostać wycofane.
Można zatem było pokusić się o „ciągłą” obserwację wyników tego zapytania i
próbę estymacji czasu potrzebnego do wyzerowania tej liczby.

W bazie 10g odpowiedź na pytanie „jak długo jeszcze” jest
banalnie prosta. Każda „długotrwała” transakcja odnotowywana jest bowiem w
perspektywie V$SESSION_LONGOPS. Dla operacji rollback graniczną wartością czasu
trwania operacji, który wyzwala odnotowanie jej jako „długotrwałej”, jest sześć
sekund. Odpowiedź na nurtujące nas pytanie znajdziemy zatem zadając zapytanie:

select time_remaining
from v$session_longops
where sid = <sid of the session doing the rollback>;

Znając już wagę informacji prezentowanych w perspektywie
V$SESSION_LONGOPS zastanówmy się, czego jeszcze możemy się stamtąd dowiedzieć.
Nie jest to perspektywa wymyślona na potrzeby 10g, ale dopiero w ostatniej
wersji bazy perspektywa pozyskała ten zestaw danych. Estymacja czasu niezbędnego
do zakończeni rollbacku wynika z analizy danych zapisanych w pozostałych
kolumnach tej perspektywy. Mamy tu więc dwie wartości TOTALWORK i SOFAR, czyli
„ile mamy do zrobienia” oraz „ile zrobiliśmy”. Oczywiście wartości te podane są
w jednostkach odpowiadających posiadanym informacjom –
w tym przypadku są to bloki. Mając informację, z jaką prędkością udawało się do
tej pory wycofywać poszczególne fragmenty operacji, możemy tym razem już całkiem
automatycznie estymować czas do zakończenia transakcji.

Po co SYSAUX?

Przez lata całe na przestrzeni tabel SYSTEM ciążył niemały
obowiązek. Nie tylko skupiała ona w sobie najważniejsze obiekty bazy, ale –
jakby z dobrodziejstwem inwentarza – bardzo łatwo stawała się śmietnikiem
danych. Odpowiedzialność za ten stan rzeczy leżała po stronie definicji
użytkownika bazy, który nie otrzymawszy jasno zdefiniowanej domyślnej
przestrzeni tabel, bardzo często bezwiednie lokował kreowane przez siebie
obiekty właśnie
w przestrzeni SYSTEM. Tak było do wersji Oracle9i. Dziewiątka pozwalała na
ustawienie domyślnej przestrzeni tabel dla użytkowników bez konieczności
każdorazowego wskazywania jej podczas tworzenia nowego użytkownika bazy.
Dziesiątka wręcz to wymusza już na etapie polecenia CREATE DATABASE. Deklaracje
tę można oczywiście później zmienić. Z takim silnym postanowieniem na poziomie
definicji bazy, każdy jej użytkownik któremu podczas wykonania polecenia CREATE
USER nie przypisano jawnie nazwy domyślnej przestrzeni tabel, otrzymuje takie
przypisanie różne od przestrzeni SYSTEM. Warto wiedzieć, że jeśli w zbiorze
użytkowników naszej bazy są tacy, którzy „odziedziczyli” ustawienie domyślnej
przestrzeni tabel po definicji bazy i tacy, którym w chwili utworzenia
przestrzeń ta została jawnie nadana, wszyscy oni otrzymają nowe ustawienia tego
parametru jeśli wykonana zostanie na bazie poleceniem:

ALTER DATABASE DEFAULT TABLESPACE <tsname>;

Tak więc jeśli użytkownik bazy U1 miał przypisaną podczas
utworzenia domyślną przestrzeń tabel P1, a użytkownik U2 odziedziczył po
ustawieniach bazodanowych domyślną przestrzeń tabel P2, to polecenie:

ALTER DATABASE DEFAULT TABLESPACE P3;

sprawi, że zarówno U1 jaki U2 będą mieli od tego momentu
przypisaną jako domyślną przestrzeń P3.

Aby sprawdzić bieżący stan tego parametru powinniśmy zadać
zapytanie:

SELECT PROPERTY_VALUE
FROM DATABASE_PROPERTIES
WHERE PROPERTY_NAME = "DEFAULT_PERMANENT_TABLESPACE";

Ale, ale – miało być o SYSAUX, a jest o bałaganie. Wróćmy do
rzeczy. W każdej bazie danych oprócz użytkowników takich jak SYS i SYSTEM są
również użytkownicy stworzeni w celu zarządzania zasobami niezbędnymi do
działania dodatkowymi funkcjonalnościami bazy, które z pewnych względów nie
zostały umieszczone w schemacie SYS. Należy do nich na przykład DBSNMP –
inteligentny agent sieci, czy ODM – właściciel zasobów data mining. Wielu
spośród tych użytkowników umieszczało domyślnie swoje obiekty w przestrzeni
SYSTEM, co stanowiło kolejny element jej rozszerzania lub – jak kto woli –
zaśmiecania. Remedium na te problemy w 10g jest zdefiniowanie drugiej
obligatoryjnej przestrzeni tabel przeznaczonej właśnie jako „druga część”
przestrzeni SYSTEM. Tak właśnie powstała przestrzeń tabel SYSAUX. Przestrzeń,
bez której nie zakończy się sukcesem realizacja polecenia CREATE DATABASE.

Czy jednak obiekty tej specjalnej grupy użytkowników są na tę
przestrzeń skazane? Nie. Ale przenoszenie ich
w inne miejsce bazy wydaje się działaniem pozbawionym sensu. Wyjątkiem mogą być
tu pojedyncze obiekty charakteryzujące się burzliwym wzrostem zapotrzebowania na
powierzchnię dyskową. Rozmiar zajmowanej przez poszczególne obiekty bazy
powierzchni dyskowej ocenić można wykorzystując informacje zawarte w
perspektywie V$SYSAUX_OCCUPANTS.

Pompowanie danych czyli
Oracle Data Pump

Narzędzia służące do ładowania i pozyskiwania do plików
danych przechowywanych wewnątrz bazy Oracle są tak stare jak sama baza. Trzeba
przyznać, ze przez lata ulegały one dosyć nieznaczącym zmianom. Stąd najwyższy
czas na zmiany większe. Zwłaszcza, że wolumeny danych powiększają się w
olbrzymim tempie i możliwość sprawnego wprowadzania dużych zbiorów danych lub
szybkiego ich pozyskiwania staje się istotnym parametrem wydajności. Podstawowym
zadaniem stawianym przed tymi narzędziami było umożliwienie przenoszenia danych
pomiędzy równymi bazami i równymi systemami operacyjnymi. Między innymi dlatego
podstawowym mechanizmem używanym do niedawna w realizacji funkcjonalności
„import” było polecenie INSERT INTO. W konsekwencji mechanizmy eksportu i
importu były raczej powolne.

Nową epokę zapoczątkowało w tym kontekście wydanie wraz z 10g
zintegrowanego narzędzia Oracle Data Pump. Jest to bowiem tak naprawdę zbiór
narzędzi działających od 10 do 15 razy szybciej od swoich poprzedników. Drugim
równie ważnym nowym elementem jest dodanie możliwości monitoringu postępu prac.
Możemy również
w pewnym sensie odpiąć się od realizowanej operacji eksportu i ponownie do jej
monitorowania podłączyć się na przykład z innego miejsca sieci. Znacząco
zwiększa to elastyczność organizacji pracy administratora i jego mobilność.

W praktyce po uruchomieniu Data Pump Export (DPE) możemy
poleceniem Control-C opuścić jego konsolę. Ponowne przywrócenie konsoli
następuje po wydaniu z poziomu systemu operacyjnego polecenia:

Export>

Aby sprawdzić, co dzieje się z zapoczątkowanym czas jakiś
temu zadaniem użyć należy komendy:

Export> status
Job: CASES_EXPORT
Operation: EXPORT
Mode: TABLE
State: EXECUTING
Degree: 1
Job Error Count: 0
Dump file: /u02/dpdata1/expCASES.dmp
bytes written = 2048
Worker 1 Status:
State: EXECUTING
Object Schema: DWOWNER
Object Name: CASES
Object Type: TABLE_EXPORT/TBL_TABLE_DATA/TABLE/TABLE_DATA
Completed Objects: 1
Total Objects: 1
Completed Rows: 4687818

Poprawę wydajności operacji eksportu uzyskać można poprzez
uruchomienie kilku procesów eksportu równolegle. Pamiętać jednak należy, że w
efekcie tych działań otrzymamy kilka plików dump. Monitoring procesów Data Pump
prowadzić można nie tylko z poziomu jego konsoli. Informacje o realizowanych
zadaniach znajdziemy również w specjalnie do tego celu przygotowanych
perspektywach bazodanowych. Podstawową perspektywą jest tu DBA_DATAPUMP_JOBS,
informująca nas o liczbie uruchomionych aktualnie procesów. Kolejna ważna
perspektywa to DBA_DATAPUMP_SESSIONS, która w połączeniu z poprzednią i
V$SESSION pozwoli dostarczyć nam informacje o SID sesji głównego procesu
drugoplanowego:

select sid, serial#
from v$session s, dba_datapump_sessions d
where s.saddr = d.saddr;

Wiedza ta pozwoli dalej śledzić estymowany czas zakończenia
tej operacji, podobnie jak ma to miejsce w przypadku monitoringu czasu trwania
rollbacku.

SQL*Plus wciąż na topie

Każda nowa wersja bazy przynosiła ze sobą nieco zmienione
zestawy narzędzi dla administratorów. Było tak również z 10g. Oczywiście
podstawą takiego oprogramowania jest od wielu już lat zestaw narzędzi
wyposażonych w interfejs graficzny, niemniej jednak wciąż nieocenione usługi
administratorom przynosi stary dobry tekstowy edytor poleceń SQL.

Oto kilka ciekawych zmian i rozszerzeń, które ułatwiają pracę
z SQL*Plus. Po pierwsze – nowy prompt. Niby nic wielkiego. Drobiazg bez
znaczenia, ale niosący ze sobą czasem jakże ważkie konsekwencje. W poprzednich
wersjach tego narzędzia uzyskanie w prompcie informacji, na koncie którego
użytkownika jesteśmy zalogowani, wymagało sporo wysiłku; teraz edytor SQL*Plus
10.1.0.2 wyposażony został w parametr umożliwiający łatwe zdefiniowanie typu
informacji, jaka winna być w tym miejscu wyświetlona. Wystarczy wydać polecenie:

set sqlprompt "_user _privilege> "

aby nasz prompt przybrał na przykład postać:

SYS AS SYSDBA>

o ile właśnie na konto takiego użytkownika z takimi właśnie
uprawnieniami dokonaliśmy logowania. Ale na tym nie koniec. Możemy dodawać do
promptu kolejne informacje. Na przykład bieżącą datę:

SQL> set sqlprompt "_user _privilege "on" _date >"
SYS AS SYSDBA on 06-JAN-06 >

identyfikator bazy danych:

SQL> set sqlprompt "_user "on " _date "at" _connect_identifier > "
SZKOT on 06-JAN-06 at TESTOWA >

i coraz precyzyjniej:

ANANDA on 06-JAN-04 at SMILEY > alter session set nls_date_format = "mm/dd/yyyy
hh24:mi:ss ";
Session altered.
SZKOT on 01/06/2006 13:03:51 at TESTOWA >

Ustawienia te można zapisać nieco bardziej permanentnie niż
na czas jednej sesji edytora, wpisując je do pliku glogin.sql. Idąc dalej
ścieżką kruczków przydatnych użytkownikom edytora, zmieniony został nieco sposób
zarządzania plikami tworzonymi poprzez zapisywanie wykonywanych w edytorze
poleceń. W poprzednich wersjach edytora dokonując szeregu prób i zapytań
mogliśmy
za każdym razem zapisać wykonane właśnie polecenie do pliku tekstowego:

select something1 ....
save 1
select something else ....
save 2
select yet another thing ....
save 3

efektem czego otrzymywaliśmy niezliczoną liczbę oddzielnych
pliczków. Teraz informacje te zbierać możemy w jednym pliku, korzystając z opcji
append:

select something1 ....
save myscripts
select something else ....
save myscripts append
select yet another thing ....
save myscripts append

Inną niedogodnością która została usunięta, jest tryb
odczytywania pliku konfiguracyjnego login.sql. W poprzednich edycjach edytora
plik ten czytany był raz przy uruchamianiu narzędzia. Skutkiem ubocznym takich
działań było to, że jeśli w treści promptu zażyczyliśmy sobie na przykład nazwy
bazy do której się logujemy, każde następne przelogowanie bez zamknięcia i
ponownego uruchomienia edytora powodowało wyświetlanie promptu niezgodnego ze
stanem faktycznym. W najnowszej wersji SQL*Plusa plik ten wczytywany jest
podczas każdej operacji logowania.

A co jeśli te zmiany nie przypadły nam do gustu?

Wpisujemy sekwencję:

sqlplus -c 9.2

i edytor zachowuje się, jak ten z wersji Oracle 9i.