af Joci Csépányi 7 år siden
425
Mere som dette
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).
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.
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.
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.
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.
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)
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).
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 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.
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).
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.
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
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.
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.
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.
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.
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.
Olyan adat olvasása, amely nem lett még jóváhagyva.
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.
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
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.