Inspiracja , wiedza , realizacja
Jsystems

W przebudowie

Login



Java

Oracle

Linux

Android

PostgreSQL

Microsoft SQL Server

Poziomy izolacji w Oracle

Data dodania: Jun 20, 2016
Data aktualizacji: Jun 20, 2016

Wprowadzenie


Współbieżność działania operacji to cecha wszystkich współczesnych baz danych. Oznacza to, że jedna operacja może modyfikować dane podczas gdy inna te same dane odczytuje, lub dwie operacje odczytują te same dane. To pociąga za sobą pewne komplikacje odnoszące się do spójności danych i odczytu.

Przykładowo – jedna operacja odczytuje dane (SELECT1), odczytana liczba wierszy to 4. Inna sesja po SELECT1 wykonuje aktualizację tych samych wierszy (UPDATE1), oraz dodaje jeszcze jeden (INSERT1) i zatwierdza. Ponowne wykonanie operacji SELECT1 spowoduje odczytanie nowego wiersza oraz wierszy zmienionych. Wynik tej samej operacji będzie różny w kolejnych wykonaniach. To może prowadzić do niepożądanych sytuacji, np. gdy zechcemy dwukrotnie wykonać zapytanie by wyrzucić ten sam raport do dwóch różnych formatów plików.

W przypadku odczytu nowego wiersza mamy do czynienia z odczytem fantomowych, w przypadku odczytu zmienionej postaci wierszy mamy do czynienia z odczytami niemożliwymi do powtórzenia.


To co widzieć będzie operacja SELECT1 będzie zależeć od poziomu izolacji transakcji. W Oracle dostępne mamy trzy poziomy izolacji transakcji. Czwarta znana z innych baz danych – READ UNCOMMITTED nie jest wspierana przez Oracle. Dostępne w Oracle:


READ COMMITED – ten tryb jest domyślny dla Oracle. W tym trybie każde zapytanie widzi tylko zmiany które zostały zatwierdzone przed rozpoczęciem zapytania. Jeśli zapytanie zostanie wykonane ponownie, w wyniku będą uwzględnione ewentualne wykonane i zatwierdzone po pierwszym (lub w jego trakcie) uruchomieniu zapytania zmiany, w tym również wiersze usunięte i dodane.

SERIALIZABLE – w tym poziomie, tylko zmiany zatwierdzone przed rozpoczęciem transakcji oraz te wykonane w ramach danej transakcji (INSERT, UPDATE,DELETE) będą widoczne. W przypadku powtórzenia tego samego selecta nie będziemy tutaj mieli do czynienia z operacjami niemożliwymi do powtórzenia, ani z danymi fantomowymi.

READ ONLY – Widoczne są tylko zmiany zatwierdzone przed rozpoczęciem transakcji. Żadne zmiany nie są możliwe w ramach sesji mającej włączony ten poziom izolacji.


Włączanie poszczególnych trybów izolacji


READ COMMITTED

Alter session set isolation_level=read committed;

Alter system set isolation_level=read committed;


SERIALIZABLE

Alter session set isolation_level=serializable;

Alter system set isolation_level=serializable;


READ ONLY

Alter session set isolation_level=readonly;

Alter system set isolation_level=readonly;


Sposób działania poszczególnych poziomów izolacji w przykładach


READ COMMITTED – domyślny

Z jednej sesji sprawdzam stan danych w tabelce regions w schemacie HR:



W osobnej sesji sprawdzam również stan, dodaję nowy wiersz i aktualizuję jeden istniejący. Nie zatwierdzam jednak transakcji:



Następnie z tej samej sesji sprawdzam stan danych w tabeli regions:



Sesja która zmieniała i dodawała dane widzi zmiany – jako dokonane przez siebie. Poprzednia sesja

nie widzi zmian:



Wiersz zaktualizowany przez drugą sesję o numerze region_id=2 pozostaje jednak zablokowany do czasu aż ta nie zatwierdzi, albo nie wycofa zmian. Moja pierwsza sesja czeka więc na zwolnienie zasobu:



Dopiero zatwierdzenie operacji z drugiej sesji:



Powoduje zwolnienie blokady na wierszu i umożliwia dokonanie zmian z pierwszej sesji, a także sprawia że pierwsza sesja widzi nowo dodany przez drugą sesję wiersz. Widziałaby i zmieniony wiersz, ale właśnie nadpisała zmiany dokonane przez sesję numer dwa.



Jak widać, dwukrotne wykonanie tego samego SELECT w przypadku gdy w międzyczasie inna sesja dokonuje zmian spowoduje, ze zobaczymy różne wyniki.


SERIALIZABLE


Włączam teraz tryb serializable i odpytuję zawartość tabelki regions.



Teraz z osobnej sesji wstawiam nowy wiersz i dokonuję zmiany na istniejącym. Obie operacje zatwierdzam.



Pierwsza sesja nie widzi jednak zatwierdzonych zmian, ponieważ posiada poziom izolacji serializable. Nie będzie tych zmian widziała tak długo, jak długo pozostaje w tym trybie.



Dopiero po wyjściu z trybu SERIALIZABLE spowodowanego wykonaniem komendy COMMIT (równie dobrze mógłbym przejść do trybu READ COMMITED standardowym poleceniem dla sesji: Alter session set isolation_level=read committed) pierwsza sesja widzi zmiany oraz nowe wiersze wprowadzone przez sesję drugą.



Teraz pewna pułapka. Uruchamiam dwie sesje, jedna z SQL Developera, druga z SQL*Plusa. W pierwszej uruchamiam tryb serializable :



Natomiast w drugiej dokonuję pewnych zmian w tabeli COUNTRIES, oraz wstawiam do niej nowy wiersz i zatwierdzam transakcję.




Teraz z poziomu sesji w SQL Developerze odpytuję tabelę COUNTRIES i..... widzę zmiany. Co się takiego stało? Czyżby tryb SERIALIZABLE nie zadziałał? Nic takiego się nie stało. Widzę zmiany, ponieważ wcześniej w ramach tej sesji nie odpytałem tabeli COUNTRIES. Gdybym to zrobił przed zmianami z poziomu sesji SQL*Plusa, nie widziałbym zmian.