Categories: All

by Joci Csépányi 7 years ago

423

Konzisztens tranzakciókezelés - zárak, olvasási és műveleti konzisztencia, undo szegmens

Az SQL92 szabvány négy izolációs szintet határoz meg a konzisztens adatolvasás érdekében, amelyeket az Oracle rendszerek is alkalmaznak. Az izolációs szintek különböző problémákat oldanak meg, mint például a jóváhagyatlan olvasás, az ismételt olvasás, és a jóváhagyott olvasás.

Konzisztens tranzakciókezelés - zárak, olvasási és műveleti konzisztencia, undo szegmens

Konzisztens tranzakcióvégrehajtás - zárak, olvasási és műveleti konzisztencia, undo szegmens

Zárak

Ugyanazon erőforrás destruktív hozzáférésének elkerülése végett az Oracle bizonyos erőforrásokat, adatokat megjelöl. Ezeket a jelöléseket záraknak (lock) nevezzük, a zár típusától függ, hogy az aktuális adaton milyen művelet végezhető el és milyen nem (ez az éppen futó utasítástól függ).

Deadlock

Két DML utasítást futtató feladat egymás által zárolt adatot próbál módosítani, így mindkettő a másikra vár. Ilyenkor az Oracle az egyiket leállítja, mivel a végtelenségig várnának egymásra.

Típusai

Az Oracle különböző zártípusokat használ különböző helyzetekben. Egy részüket a felhasználók is elhelyezhetik bizonyos objektumokon. Azokhoz a műveletekhez, amelyekhez szükséges zárakat alkalmazni, az Oracle automatikusan alkalmazza őket. Néhány zárat a felhasználó nem, csak az Oracle helyezhet el.

Belső zárak

Az Oracle az adatbázis működése közben a háttérben menedzseli a szükséges erőforrásokat (például memória), ezek lefoglalására ilyen zárakat alkalmaz. Mivel ilyen alacsony szintű műveleteket a felhasználónak nem szükséges végeznie, így ezeket nem helyezheti el felhasználó, csupán a rendszer.

Szótárzárak (DDL zárak)

A szótárzárak megakadályozzák más DDL utasításokkal való interferenciát ugyan azon az objektumon. Minden adatmódosító tranzakció elhelyez az adott táblán egy DDL zárat is, ezzel garantálva hogy az objektum definíciója nem változik a tranzakció közben.

Feltörhető zár

Ez a típusú zár minden SQL utasításkor létrejön minden objektumra, amre található referencia az SQL-ben. Ez nem akadályoz meg DDL utasításokat, ha közben egy DDL fut le, akkor az feltöri ezt a zárat (innen a név). Azért hasznos ez a fajta zár, mert feltöréskor az éppen futó SQL utasításban levő referenciáról tudni lehet, hogy módosult (például fut egy SELECT, és közben dobják az egyik táblát amiből dolgozott, akkor a SELECT azonnal visszatér egy hibával, hogy a referencia objektum már nem elérhető (feltéve hogy a SELECT nem rakott más típusú zárat a táblára)).

Megosztott DDL zár

Ez az exkluzív DDL zár enyhébb formája. Bizonyos DDL utasítások megengedik, hogy a hozzá hasonló DDL utasítások vele együtt futhassanak, de más destruktív utasítások ne módosíthassák az objektumot.


Például a CREATE PROCEDURE utasítás megosztott zárat helyez el a szükséges objektumokon, amely nem tiltja más CREATE PROCEDURE utasításnak ugyanezek objektumok használatát, a két utasítás megosztva zárolja az objektumot egyidőben. A megosztott zár viszont nem engedi például a DROP TABLE utasítás végrehajtását.

Exkluzív DDL zár

Ez a leggyakoribb DDL zár, megakadályozza az aktuális DDL utasítással ellentmondó DDL utasítások futását (például nem lehet eldobni azt a táblát amelyiken éppen egy ALTER TABLE-ben egy új oszlop íródik). A különbség a táblazár és az exkluzív DDL zár között, hogy míg a táblazár semilyen olyan műveletet nem enged, amely a táblában levő módosuló adatokat sértheti, addig az exkluzív csak azokat nem engedi, amely DDL utasítások ellentmondóak az éppen futóval.

Adatzárak (DML zárak)

A DML zárak lényege, hogy két egyidejű DML vagy DDL utasítás ne zavarja egymást, és csak akkor lehessen módosítani az adatot, ha már az előző folyamatoknak nincsn szüksége rá.

Táblazár

Feladatuk garantálni, hogy a tranzakció által módosított tábla definíciója ne változzon (DDL utasítástól), míg a tranzakció be nem fejeződik. Ez a típusú zár nem akadályozza a tábla adatainak módosítását.


Például ne fordulhasson elő olyan helyzet, hogy a tranzakció módosít egy 6 mezőből álló sort, de mire befejezi, már csak 5 oszlopa van a táblának.

Sorzár

Az Oracle akkor alkalmaz sorzárat, amikor egy tranzakciónak módosítania kell egy sort. Teszi ezt azért, hogy más tranzakció ne tudja addig módosítani, míg az előtte levő be nem fejeződött. A sorzár a legkisebb egységű zár, ennél kisebb egység zárolására (pl. mező) az Oracleben nincs lehetőség.


Az olvasók nem várnak az írókra, ők a before imaget látják az éppen módosuló soroknál. Az írók nem várnak az olvasókra, kivétel a SELECT FOR UPDATE-tel olvasott adatokra. Az írók csak akkor várnak másik írókra, ha pontosan ugyan azt a sort akarják módosítani.


Egy táblában ha van sorzár, automatikusan kap a tábla egy táblazárat is, hiszen a tábladefiníció változtatásával az éppen írott sorok is változhatnának (pl törlünk egy oszlopot, az a zárolt sorból is törlődne, amelynek eredménye még nem végleges)

Módosítás

Undo táblatér

Az undo táblatérben találhatóak az undo szegmensek, amelyeknek nagy szerepe van a módosításra váró adatok tárolásában illetve a módosítás előtti adatok olvasásában (amikor erre szükség van). Több ilyen táblatér is létezhet egyszerre, azonban aktívan mindig csak egyet használ a rendszer. Más szegmenstípusok ebben a táblatérben nem hozhatók létre (pl indexek vagy táblák).

Undo szegmens

Az undo szegmens a tranzakciók jóváhagyásában vagy rollbackjében játszik nagy szerepet.


Egy tranzakciónál előfordulhat, hogy mindent vissza akarunk állítani a tranzakció előtti állapotra, ezért a régi (before image) és az új értékeket (after image) is tárolnunk kell valahol. Mivel a tranzakciók többsége jóváhagyással végződik így célszerű az új adatokat az eredeti táblában tárolni, a régi adatok pedig belekerülnek az undo szegmensbe.

Olvasási konzisztencia biztosítása

Mivel fontos az adott időben

Pointerek

Az Oracle a pointerek segítségével tudja beazonosítani, hogy az adott cella adata hol található meg az undo szegmensben: ha a cella lockolva van, akkor megkeresi a hozzá tartozó pointert, annak mentén eljut az undo segmentben a megfelelő értékhez, majd azt adja vissza olvasásra.

Sikertelen tranzakció visszaállíátsa

Sikertelen tranzakció esetén ugyan az történik, mint rollback esetén.

Ciklikus szegmenshasználat

Az undo táblatérnek fix mérete van, azonban előre nem tudjuk hogy mekkora szegmensre van szükség, így ha megtelik és a végére ér, akkor elindul a szegmens elejéről és a nem zár alatt levő adatokat elkezdi felül írni az Oracle (amelyek zárolva vannak az undo szegmensben, azok a tranzakciók még nincsenek lezárva, azok before imagére mindenképp szükség van még). Ezt a méretet a DBA megváltoztathatja.

Rollback

Rollback esetén az undo tartalma visszaíródik a táblába. A rollback átlagosan 1.5x annyi időbe telik, mint a commit, de nem probléma mert a tranzakciók többsége committal végződik.

After image

After imagenek nevezzük a tranzakció kimeneti értékét. Ez az adat még nem feltétlenül végleges. Módosítás alatt ez tárolódik magában a táblában, az eredeti before image átmásolódik az undo szegmensbe, keletkezik egy pointer, amely a before imagere mutat az after imageről.

Before image

A módosítás előtti, eredeti érték. Ez a módosítás alatt az undo segmentben van. Egy cellának lehet több before image is, ezek pointerrel mutatnak ilyenkor mindig az eggyel régebbi adatra (ha nem íródnak felül).

Olvasás

A konzisztens olvasást az SQL92 szabvány szabályozza, amely 4 izolációs szintet különböztet meg, melyek három feloldandó jelenségre kínálnak különböző megoldásokat. Ez az Oracleben beállítás kérdése, így fontos tudni mind a felhasználónak, mind a DBA-nak, hogy milyen olvasási beállítások vannak jelenleg érvényben.

Sikertelen olvasás okai
Erőforrásproblémák

Erőforrásproblémák miatt is hibával térhet vissza a SELECT. Ennek több fajtája is lehet, például a felhasználó a rá kiosztott erőforráskeretet túllépte, ezért a rendszer megszakítja az olvasást, vagy magának a szervernek az erőforrásai merülnek ki.

Időtúllépés

Memória túllépés

Olvasási zár problémák

Ilyen a SELECT FOR UPDATE utasítással fordulhat például elő, amely a kiolvasás után lockolja a kiolvasott adatokat. Ha ennek a NOWAIT klauzulája fut, akkor nem fog várni a már jelenlévő zárak feloldására, hanem hibaüzenettel tér vissza.

Hiányzik a before image

Az Oracle alapbeállítása olvasásra a Jóváhagyott olvasása ("Read committed"), amely megnézi hogy az adat mikor volt módosítva (vagy most éppen módosítják-e). Ha igen, akkor a korábbi értéket kikeresi az undo szegmensből, ott azonban a jóváhagyott értékek megmaradása nem garantált, így ha az érték már felülíródott, az egész kiolvasás hibával tér vissza.

Feloldandó jelenségek
Nem utasításszintű konzisztens olvasás

Az utasításszintű konzisztens olvasás azt hivatott biztosítani, hogy az akkori adatot lássák a felhasználók, amikor lefuttatták a SELECT utasítást. Előfordulhat, hogy miközben a SELECT már fut, módosítanak és jóváhagynak egy adatot. Az utasításszintű konzisztencia szerint ekkor is a régi, módosítás előtti értéket kell visszaadni.


A régi értéket az undo szegmensben keresi, a pointer mentén találja meg az adatot. Ha többször volt módosítva a SELECT futása alatt, akkor több before imaget tartalmaz az undo segment, ahol az újabb mindig pointerrel mutat a régebbire. Ha a pointer már egy felülírt adatra mutat, akkor az Oracle hibát ad vissza (lsd.: hiányzik a before image)


Az Oracle ezt alapvetésnek tekinti, nincs olyan beállítása, ahol ez ne teljesülne.

Fantom olvasás

Egy tranzakció kétszer kiolvassa az adatokat egymás után ugyanazokkal a szűrési feltételekkel, de másodszorra egy módosító tranzakció miatt már több sor felel meg a kritériumfeltételnek.

Nem megismételhető olvasás

Egy tranzakció kétszer olvassa ki ugyanazt, azonban nem egyezik az eredményük, mert sorok módosítva vagy törölve lettek a két olvasás között.

Dirty read

Olyan adat olvasása, amely nem lett még jóváhagyva.

Izolációs szint
Serializable
Ismételt olvasás

Angolul: repeatable reads. Ez a mód megoldást kínál a nem megismételhető olvasás problémára azáltal, hogy zárolja az adatokat amik olvasásra kerülnek. Ennek előnye hogy tudja garantálni az olvasás indításának időpontjában levő állapot garantált sikeres kiolvasását. Hátránya hogy ezen adatok olvasás közben sem módosíthatóak. A fantom olvasást nem tudja kiküszöbölni.

Jóváhagyott olvasás

Angolul read committed. Ez az Oracle alapbeállítása, ebben csak a jóváhagyott adatokat adja vissza eredményként az olvasás. Az éppen módosuló adatnál nem ad vissza hibaüzenetet, hanem megkeresi az undo szegmensben a before imaget (módosulás előtti értéket) és azt adja vissza, a felhasználó nem látja hogy az érték éppen módosul, hanem szimplán az eredetit kapja vissza. Ez a mód azonban nem tudja garantálni a nem megismételhető olvasás és a fantom olvasás jelenségek kiküszöbölését.


Kép a mellékelt linken!


Forrás:

docs.oracle.com/cd/B28359_01/server.111/b28318/consist.htm#CNCPT621

Jóváhagyatlan olvasás

Ez a legmegengedőbb izolációs szint, minden érték ami a táblában szerepel kiolvasásra kerül, akár jóvá van hagyva, akár nem. Ez problélmás, hiszen a felhasználó nem tudja hogy az adatok amiket visszakapott véglegesek vagy éppen csak valaminek a részeredménye. Ez a szint kerülendő, így az Oracle nem is támogatja, nincs olyan beállítás amely engedélyez dirty readet.