Słówko o segmencie wycofania

W domyślnej konfiguracji Oracle sugeruje (np. w Oracle Installerze) tworzenie stosunkowo niedużych segmentów wycofania (rollback segment). W praktyce potrzebne są istotnie większe. Poniżej piszę dlaczego.

Segment wycofania jest wykorzystywany do rejestracji oryginalnych wartości rekordów zmienionych przez jeszcze nie zatwierdzone transakcje. Ile razy robimy INSERT, UPDATE czy DELETE, do segmentu wycofania zostaje wpisana oryginalna treść zmienianego/usuwanego rekordu (bądź informacja, że dany nowy rekord jest nowy). Zawartość segmentu wycofania może być czytana w dwóch sytuacjach:

  • przy wycofywaniu transakcji (czy to wynikającym z wydania polecenia ROLLBACK, czy to z jakiegoś błędu po którym Oracle samo cofa transakcję) - Oracle pobiera poprzednie wartości aby powtórnie wpisać je do tabel danych;
  • przy udostępnianiu danych zapytaniom rozpoczętym wcześniej, niż transakcja, która te dane zmieniła.

Może słówko objaśnienia dla drugiego przypadku: przypuśćmy, że uruchamiamy duże zapytanie SELECT generujące jakiś raport. Zaczyna działać, znajduje pierwsze rekordy, powoli przechodzi coraz dalej. W międzyczasie uruchamiamy mniejszą transakcję która modyfikuje zawartość naszej tabeli - w tym kilku rekordów "dotykanych" przez nasze zapytanie - i COMMITujemy ją. Gdy duże zapytanie dochodzi wreszcie do tych rekordów, próbuje pobrać z segmentu wycofania wartości, jakie miały one w chwili rozpoczęcia tego zapytania - i to one zostają zwrócone. Zresztą to samo się dzieje przed COMMITem małej transakcji.

Gdy nasz segment wycofania jest za mały, grożą nam dwa istotne problemy:

  • transakcja przeprowadzająca modyfikacje może zostać przerwana z powodu braku miejsca w rollback segmencie;
  • długotrwałe zapytanie SELECT może zostać przerwane z tajemniczym błędem Snapshot too old.

Pierwszy z tych błędów jest jasny: Oracle nie ma już gdzie skopiować oryginalnych wartości, więc musi przerwać transakcję. Komunikat o błędzie też jest prosty i zrozumiały. Łatwo więc sobie pomyśleć cóż, jeśli segment wycofania się przepełni, dodam nowy, na razie nie ma co się przejmować. Niestety, w praktyce wygląda to tak: puszczamy duże UPDATE lub DELETE, po 5 godzinach działania wywraca się ono z powodu przepełnienia segmentu wycofania a następnie przez 5 godzin Oracle wycofuje efekty niedokończonej transakcji. Co gorsza, przez ten czas wszystkie rekordy objęte przez pechową transakcję są zablokowane i nie możemy nic zrobić, by uzyskać do nich dostęp! Dlatego lepiej, by segment wycofania był "większy niż nasze największe transakcje".

Drugi błąd dotyczy opisanego wyżej drugiego zastosowania segmentu wycofania: puściliśmy długo działającego SELECTa, w międzyczasie realizowane były rozmaite transakcje modyfikujące bazę danych. Nasze długie zapytanie dochodzi do pewnego rekordu, który został zmodyfikowany już po jego rozpoczęciu - i Oracle próbuje znaleźć w segmencie wycofania oryginalną wartość. Jeśli jej nie ma, otrzymujemy błąd Snapshot too old. Skąd się to bierze? Ano stąd, że po zatwierdzeniu (COMMIT) transakcji, która wprowadzała zmianę, informacje o tym, co ona zmieniła pozostają w segmencie wycofania - ale tylko tak długo, jak długo jakaś nowa transakcja nie potrzebuje miejsca (obowiązuje prosta zasada - jeśli nie ma już wolnych bloków, reużywane są bloki w których przechowywano informacje o najstarszej transakcji). Innymi słowy: nie musimy nawet mieć transakcji robiących duże modyfikacje - jeśli realizujemy bardzo dużo drobnych UPDATE, nasze długotrwałe SELECT-y mogą być przerywane. Co gorsza, przy "trochę za małym" segmencie wycofania całkiem prawdopodobny jest scenariusz, w którym nasz duży SELECT zostanie przerwany po 8 godzinach działania i przetworzeniu 98% rekordów, uruchomiony ponownie, znów przerwany po 8 godzinach i tak w kółko. Zatem musimy mieć w segmencie wycofania dosyć miejsca na wszystkie transakcje realizowane w czasie działania długotwałego zapytania. Jeśli grozi nam uruchamianie 12-godzinnych SELECT-ów, powinniśmy mieć segment wycofania, w którym zmieszczą się wszystkie transakcje realizowane w ciągu 12 godzin.

Jeszcze uwagi dodatkowe: Oracle pozwala zarówno na śledzenie poziomu wykorzystania segmentów wycofania, jak na dodawanie nowych segmentów wycofania w locie, bez zatrzymywania bazy danych. Składnię pozwolę sobie pominąć, podręczniki Oracle omawiają to wyczerpująco.

komentarze obsługiwane przez Disqus