czwartek, 12 kwietnia 2012

Flashback w Oracle


Czym są dane UNDO

Czy zadałeś sobie kiedyś pytanie, co się właściwie dzieje kiedy wywołujesz rollback? Albo dlaczego przed commitem zmiany widzisz tylko Ty, a nie widzą ich inni użytkownicy? Te same dane muszą istnieć w dwóch postaciach : tej zmienionej i tej oryginalnej sprzed zmiany. Takie oryginalne dane (sprzed zmany) są nam potrzebne co najmniej w kilku sytuacjach:

  • Kiedy wywołujesz rollback – dane oryginalne muszą zostać przywrócone.
  • Kiedy rozłączasz sesję bez zatwierdzenia zmian – dane oryginalne muszą zostać przywrócone.
  • Kiedy inni użytkownicy przeglądają dane które Ty właśnie zmieniasz a jeszcze nie zatwierdziłeś – muszą widzieć dane oryginalne.
  • Kiedy przywracasz stan obiektu np. tabelki do punktu w czasie – odczytany musi zostać stan tego obiektu we wskazanym czasie.


Jak to wszystko właściwie się odbywa? Za każdym razem kiedy wykonujesz jakiekolwiek operacje DML ( DELETE, UPDATE,INSERT, MERGE), oryginalny stan danych które zmieniasz zostaje zapisany jako dane UNDO. Dane UNDO są z kolei zapisywane w tablespace UNDO (który wcale nie musi się tak nazywać). W bazie może być kilka tablespace'ów przeznaczonych do przechowywania danych UNDO, jednak w aktualnym użyciu może być tylko jeden. W tabeli undo znajduje się więc postać danych sprzed zmiany z informacją co to za dane oraz z kiedy pochodzą.
Po zakończeniu transakcji dane pozostają w UNDO, dzięki czemu możemy korzystać z FLASHBACK i np. przywrócić tabelę do stanu z określonego czasu. Jak długo te dane znajdują się w tablespace UNDO? To zależy od ustawienia parametru UNDO_RETENTION , rozszerzalności tablespace'u oraz ustawień gwarancji. Tym wszystkim zajmiemy się nieco później.





Dane UNDO a REDO logi

Musisz pamiętać o tym, że dane UNDO a archivelogi to dwie zupełnie różne rzeczy i służą do różnych celów. Przede wszystkim , archivelogi są tworzone na podstawie plików dziennika powtórzeń – a więc w pewnym sensie zawierają historię zmian nie zaś dane. Archivelogi mogą być tworzone lub nie, w zależności od włączenia trybu ARCHIVELOG. Instancja nie mogłaby w zasadzie funkcjonować bez danych UNDO. Bez nich nie byłaby możliwa żadna operacja DML. Różny jest też cel stosowania danych UNDO i REDO logów. Archivelogi wykorzystywane są przede wszystkim do odtwarzania bazy danych. Są czytane , a następnie zmiany które są w nich zawarte są aplikowane na bazie danych po odtworzeniu fizycznym plików z backupu.


Korzyści z wykorzystania FLASHBACK


Dzięki odtwarzaniu FLASHBACK które opiera się o dane UNDO jesteśmy w stanie:

  • Odtwarzać pojedyncze obiekty – np. tabele , bez potrzeby odtwarzania całej bazy czy tablespace.
  • Odtwarzanie z użyciem FLASHBACK jest znacznie szybsze niż odtwarzanie z backupu
  • Nie musimy wyłączać instancji , ani offline'ować całego tablespace by odtworzyć obiekt.



Co z tego wszystkiego wynika – czyli praktyczne wykorzystanie przestrzeni UNDO



Flashback Query

Wykorzystując dane które znajdują się w przestrzeni UNDO, możemy spojrzeć na stan danych z określonego czasu. Może mi to być potrzebne do określenia czasu do którego trzeba odtworzyć tabelę po błędnych operacjach, lub po prostu do porównania stanów. Przykład :

  1. Sprawdzam wynagrodzenie pracownika o id 100 w tabelce employees znajdującej się w schemacie użytkownika hr.
  2. Widzę że jego aktualne wynagrodzenie wynosie 24000 , więc zmieniam je na 22000 i zatwierdzam zmiany. Dla pewności sprawdzam, zmiany zostały dokonane.





  1. Chciałbym teraz dowiedzieć się, jak te dane wyglądały kilka minut temu. Sprawdzam jak wyglądają teraz.
  2. Przy użyciu klauzuli „as of timestamp” jestem w stanie podejrzeć dane z określonego czasu. Aby ten punkt w czasie do którego się odnoszę podać, posługuję się funkcją to_timestamp. Wyświetlone dane pochodzą z przestrzeni UNDO.








Klauzula „as of timestamp” występuje zawsze po nazwie tabeli do której operacja się odnosi. Wszelkie warunki występują po niej.
Mogę teraz wykonać flashback tabeli do punktu w czasie , i w ten sposób odzyskać stan obiektu w danym momencie. Co jednak jeśli dokonanych zostało wiele zmian, a ja nie wiem dokładnie w którym momencie dane znajdowały się w pożądanym przeze mnie stanie? Mogę sprawdzić różne wersje tych danych na przestrzeni czasu z użyciem Flashback Versions Query.


Flashback Versions Query

Jak wspomniałem wcześniej, flashback versions query pozwoli Ci porównać różne wersje tych samych danych na przestrzeni czasu. Najlepiej jeśli pokażę to na przykładzie. Sprawdzam najpierw ile aktualnie wynosi wynagrodzenie pracownika o id 103.




Następnie dokonuję kilku zmian wynagrodzenia, zatwierdzając je. Zmiana pierwsza:


Zmiana druga:




Chcąc porównać te same dane na przestrzeni czasu muszę posłużyć się klauzulą „versions between timestamp” zaraz po nazwie tabeli i wskazać zakres czasu który mnie interesuje. Pierwsza wartość zawsze musi być mniejsza:




Wyświetliłem tutaj również pseudo kolumnę versions_starttime która informuje mnie kiedy ta zmiana została dokonana. Do dyspozycji mam również kolumny:

  • versions_endtime – czyli do kiedy ta wersja danych obowiązywała
  • versions_startscn – scn podczas dokonania zmiany
  • versions_endscn – ostatni scn w czasie obowiązywania tej wersji danych
  • versions_operation – jaką operacją dane zostały zmienione



FLASHBACK tabeli ( Przywracanie tabeli do punktu w czasie )


Kiedy już jestem w stanie określić do jakiego czasu chcę przywrócić obiekt, mogę posłużyć się FLASHBACKIEM do dokonania tej czynności. Nie muszę wyłączać instancji , ani tablespace'a. Dane przywracane są z przestrzeni UNDO.


Pierwsze co muszę wykonać to włączyć „row movement” dla tabeli którą będę przywracał. Robi się to tylko raz dla tabeli. Nie musimy tego robic przed każdym przywracaniem.




Następnie przywracamy tabelę , podając czas do którego chcemy przywrócić przy pomocy funkcji to_timestamp. Nie musi być to dokładnie czas powstania wersji , który możemy zobaczyć stosując zapytanie z „versions between”. Ważne by trafić czas w którym interesująca nas wersja obowiązywała. Ja przywróciłem tabelę do stanu przed wszystkimi zmianami, do wersji początkowej:



Jeszcze mała weryfikacja:




Oczywiście nie możemy cofać się dowolnie daleko w przeszłość. Warunkiem przywrócenia tabeli do danego punktu w czasie , jest istnienie danych z tego okresu w przestrzeni UNDO. Przy użyciu takiej metody nie przywrócimy jednak tabeli która została usunięta. Aby to zrobić musimy posłużyć się nieco inną metodą, mianowicie „Flashback before drop”


Flashback before drop (Przywracanie tabelki po skasowaniu)


Ta funkcjonalność dostępna jest dopiero od wersji 10g. Tak więc jeśli zdarzy Ci się skasować tabelkę w 9 albo starszej wersji , to niestety konieczne będzie odtwarzanie bazy do punktu w czasie. Jako administrator możesz oczywiście uniemożliwić przywracanie skasowanych tabel :

alter system set recyclebin=off scope=spfile;

Po przestawieniu tego parametru musisz zrestartować instancję, aby nowe ustawienia zostały uwzględnione. Oczywiście możesz go również przywrócić:


alter system set recyclebin=on scope=spfile;


Nie musisz go włączać jeśli wcześniej nie wyłączałeś, ponieważ parametr ten domyślnie jest włączony.


Przyjrzyjmy się bliżej jakie mamy możliwości. Najpierw kasujemy tabelę:




Możemy teraz zajrzeć do naszego śmietnika z perspektywy użytkownika kasującego obiekt:




Widzimy że znajduje się w śmietniku przed momentem skasowana tabelka. W słowniku user_recyclebin widzimy tylko obiekty skasowane przez nas. Administrator może przejrzeć wszystkie skasowane obiekty w słowniku dba_recyclebin:



Jeśli obiekt znajduje się w śmietniku , to można go przywrócić:




Gdybyśmy jednak po skasowaniu stworzyli nowy obiekt o takiej samej nazwie jak ten skasowany , lub po prostu chcieli odtworzyć obiekt z nową nazwą możemy dodać klauzulę „rename to”:





Możesz też w przypadku konkretnych obiektów skasować je trwale. Tak by nie można ich było przywrócić flashbackiem. Dodajemy wtedy klauzulę „purge” przy kasowaniu:





Obiekt jak widać nie jest tym razem widoczny w śmietniku i nie można go odtworzyć.
Jeśli chciałbyś trwale usunąć wcześniej zdropowany obiekt tj. skasować go ze śmietnika:




możesz posłużyć się klauzulą „purge table”:





Sposób działania przywracania po skasowaniu jest nieco inny niż w przypadku przywracania do punktu w czasie. W przypadku kasowania, obiekt nie trafia do przestrzeni UNDO. Po prostu miejsce które zajmował w swoim tablespace jest oznaczane jako „do zapisu”. Dane ze skasowanej tabeli tak naprawdę nadal istnieją. Miejsce w którym znajdowała się tabela zostaje nadpisane dopiero kiedy nie będzie już wolnej przestrzeni w tablespace, a sam tablespace nie będzie mógł się rozszerzyć. W praktyce oznacza to , że takie skasowane tabele będą przywracalne przez bardzo długi okres, niezależnie od ustawień UNDO_RETENTION i własności przestrzeni UNDO.

Czasem przywracanie pojedynczych obiektów niestety nie wystarczy, musimy przywrócić bazę do punktu w czasie...


FLASHBACK database (Przywracanie bazy do punktu w czasie przy użyciu FLASHBACK)

Pamiętaj że przywracanie bazy przy użyciu FLASHBACK to zupełnie inny mechanizm niż przywracanie bazy danych przy użyciu backupu i archivelogów. Tutaj co prawda również są wykorzystywane archivelogi, ale nie potrzebujesz przywracania plików z backupu. Dane przywracane są z tzw. FLASHBACK LOGÓW do stanu przed momentem do kŧórego przywracamy , a następnie zmiany do wskazanego przez nas momentu doczytywane są z archivelogów. Oczywiście alternatywnie można posłużyć się zwyczajnym przywracaniem do punktu w czasie, jednak jeśli mamy do wyboru odtwarzanie z backupu mającego tydzień , a później doczytywanie archivelogów albo zaczytanie flashback logów i doczytanie minimalnej ilości archivelogów, to porównianie szybkości przyniesie oczywiste efekty. Aby przywracanie bazy z użyciem flashback działało, musimy mieć włączony tryb ARCHIVELOG bazy. Włączamy go jeśli jeszcze tego nie zrobiliśmy:





Musimy teraz przeprowadzić konfigurację wstępną , niezbędną do przywracania bazy danych z flashbacku. Konfigurację przeprowadzamy będąc w trybie MOUNT EXCLUSIVE. Logi flashback będą znajdować się w FRA, będą cyklicznie nadpisywane. Musimy więc ustalić czas do jakiego ewentualnie będziemy się cofać. Nie jest to wartość sztywna, jedynie orientacyjna. Czas ten określamy poprzez parametr db_flashback_retention_target podając czas w minutach. Ustawiłem 1440 minut czyli dobę. Następną czynnością jest włączenie wytwarzania logów flashback instrukcją alter database flashback on; To czy baza wytwarza logi flashback czy nie , możemy zweryfikować sprawdzając parametr flashback_on ze słownika v$database. Możemy również wyłączyć wytwarzanie logów flashback instrukcją alter database flashback off (również w trybie mount exclusive).



Konfiguracja za nami, przeprowadźmy więc test. Ja zmienię jedną tylko tabelkę a następnie odtworzę całą bazę przy użyciu flashback , jednak to jest tylko w celach testowych – pamiętamy że możemy przywracać pojedyncze obiekty, nie ma potrzeby w takiej sytuacji odtwarzać całej bazy.
Zalogowałem się jako użytkownik HR i sprawdzam aktualny stan zarobków w firmie:




Dokonuję więc zmiany wynagrodzenia dla wszystkich pracowników:



Przywrócę bazę z użyciem FLASHBACK. Aby to zrobić, muszę być w trybie MOUNT EXCLUSIVE. Po takim odtwarzaniu muszę otworzyć bazę z RESETLOGS:




Sprawdzam po przywróceniu czy moje dane wróciły do pierwotnej postaci:



Jest ok. Teraz drogi czytelniku, spróbuj odtworzyć bazę danych do tego samego punktu przy użyciu metod „tradycyjnych” tj . Restore , recover i porównaj czasy wykonania :)
Mimo że na pozór ta metoda wydaje się być świetna, to pamiętaj że ma też swoje ograniczenia. Ponieważ logi flashback są cyklicznie nadpisywane, możliwość powrotu do punktu w czasie jest ściśle uzależniona od tego, czy logi zostały już podmienione czy nie. Mógłbyś chcieć mieć np. punkty do których zawsze możesz powrócić , nawet po długim czasie. Możesz po prostu przechowywać backupy i archivelogi potrzebne do odtworzenia do danego momentu, ale taką funkcję spełniają również Gwarantowane Punkty Przywracania.....



Gwarantowane Punkty Przywracania (Guaranteed Restore Point)

Przy użyciu tej funkcjonalności , możesz utworzyć punkt do którego będziesz mógł wrócić zawsze niezależnie od ustawień parametru db_flashback_retention_target. Działa to podobnie jak „save” w grach. Baza zapisuje pod wyznaczoną przez Ciebie nazwą swój stan na dany moment. W razie potrzeby zawsze możesz do tego punktu powrócić.


Taki punkt przywracania tworzysz przy normalnie otwartej i działającej instancji. Możesz ich utworzyć wiele. W razie potrzeby odtwarzanie do takiego punktu przebiega bardzo szybko. Wskazujesz tylko do jakiego punktu przywracania odtwarzać chcesz bazę.




Przywracanie do takiego punktu również wykonujemy w trybie MOUNT EXCLUSIVE. Po wszystkim otwieramy bazę z RESETLOGS.

Flashback ma jeszcze jedną ciekawą własność. Pozwala cofnąć się przed RESETLOGS:



Aby świat nie był zbyt piękny a adminka zbyt prosta pamiętaj też o ograniczeniach. Nie będziesz mógł odtworzyć bazy flashbackiem jeśli :
  • plik kontrolny był odtwarzany
  • Skasowano tablespace
  • zmniejszono plik danych

1 komentarz:

  1. A jakie są drawbacki używania flashbacka (w szczególności restore points?) Czy narzut jest na zapis (jak w macierzy - coś a'la copy on the write z przestawieniem znacznika?)
    Jak z miejscem dla gwarantowanego punktu odtwarzania i działającego potem flashbacku? Może dopisałbyś jak z kasowaniem i zarządzaniem flashbackami?

    OdpowiedzUsuń