2007. december 3., hétfő

Architektúra part #3 – Tranzakciókezelés

A tranzakció legalább egy SQL utasítást magába foglaló műveletsorozatot jelent. Elemi műveletként értelmezzük, ami annyit tesz, hogy a tranzakciót alkotó SQL utasítások mindegyike végrehajtódik (commitálódik), vagy egyik sem (roll back – visszagörgetés). Egy tranzakció jóváhagyása vagy visszagörgetése explicit módon a COMMIT vagy ROLLBACK utasításokkal, implicit módon az alkalmazásból való kilépéssel vagy egy DDL utasítás végrehajtásával történhet.
Utasítás szintű visszagörgetésről akkor beszélünk, ha egy SQL utasítás valamilyen hiba folytán nem tud lefutni. Ilyen hiba lehet például, ha már létező elsődleges kulcsot akarunk létrehozni, ha két SQL utasítás között versenyhelyzet áll elő, vagy egyszerűen csak szintaktikailag nem helyes az utasítás. A hibás utasítás nem okozza az egész tranzakció visszagörgetését, pusztán csak a saját feladatát nem tudja végrehajtani.

Nagy adatbázis műveletek számára előnyös lehet, hogyha egy tranzakció helyfoglalási problémák következtében nem tud tovább futni, akkor nem visszagörgetés következik, hanem lehetősége van az adatbázis adminisztrátornak a hibát elhárítania, majd a tranzakciók zökkenőmentesen futhatnak tovább. (Resumable space allocation)

Egy tranzakció futásának kezdetén a visszagörgetéshez szükséges információk tárolására hozzárendelünk a tranzakcióhoz egy undo tablespacet. A tranzakció végén a következők állhatnak elő:
  • a felhasználó COMMIT vagy ROLLBACK utasítást ad ki.

  • a felhasználó valamilyen DDL utasítást (CREATE, DROP, RENAME vagy ALTER) ad ki. Ebben az esetben az adatbázis először commitálja a tranzakciót, majd csak azután hajtja végre a DDL utasítást, mint egy egy utasításból álló külön tranzakciót.

  • a felhasználó kapcsolatot bont az adatbázissal. Ekkor automatikusan commit hajtódik végre.

  • a felhasználói processz abnormálisan áll le. Ekkor automatikusan rollback hajtódik végre.


Commitálni egy tranzakciót annyit tesz, mint véglegesíteni az adatbázisban az SQL utasítások által végzett műveleteket. A commit előtt az adatbázis a következő műveleteket hajtja végre: undo információkat generál, melyek a az SQL utasítások által módosított adatok módosítás előtti változatát tárolják. Illetve az SGA redo log bufferjébe redo log bejegyzéseket tesz, melyek az adatblokkokon illetve roll back blokkokon történt változásokat rögzítik. Előrefordulhat, hogy ezek az adatok a tranzakció commitálását megelőzően már a lemezre kerülnek. A commit után a következők mennek végbe:
  1. az undo tablespacehez tartozó belső tranzakciós táblában feljegyezzük, hogy a tranzakciót commitálták, s beírjuk a tranzakció egyedi SCN (system change number) számát.

  2. az SGA redo log bufferjének redo log fájljába bejegyzéseket tesz az LGWR (log writer process), s szintén beírja a tranzakció SCN számát, ami egyben a tranzakció commitálását is jelenti.

  3. az adatbázis elengedi a tranzakció által használt zárakat.

  4. a tranzakciót késznek jelöli.


Egy tranzakció visszagörgetése (roll back) annyit jelent, hogy egy lezáratlan tranzakció minden addigi adatmódosítását visszaállítjuk az adatok eredeti értékére. A régi adatokat az undo tablespaceben, a változtatásokat a redo logban tároljuk. Lehetőség van savepointok definiálására, amikkel egy nagyobb tranzakciót kisebb részegységekre bonthatunk, így ha valahol hiba történik, akkor a visszagörgetés nem teljesen a tranzakció elejéig történik, hanem a legutolsó savepointig (már ha volt addig). A visszagörgetés a következő lépésekből áll:
  1. az adatbázis az undo tablespace alapján minden addigi, a tranzakció SQL utasításai által végrehajtott módosítást visszacsinál. Savepoint esetén természetesen csak az adott savepointig kell visszacsinálni mindent, vagyis csak a savepoint után szereplő SQL utasítások által módosított adatokat kell a régi értékükre visszaállítani.

  2. Ha volt savepointunk, akkor azt az adott savepointot természetesen megőrizzük, de minden utána megállapított savepointot törlünk.

  3. Elengedjük a tranzakció zárjait. Természetesen ha savepointot alkalmaztunk, akkor itt is csak a savepoint után igényelt zárakat engedjük el. Azok az adatok, melyek a savepoint előtt már zárolva voltak, természetesen továbbra is zárolva maradnak.


Kétfázisú commit működési elve:
Egy elosztott adatbázisban hálózati vagy rendszer hibák esetén is gondoskodni kell a hálózat feletti tranzakcióvezérlésről és az adatok konzisztenciájáról. Elosztott tranzakciónak nevezünk egy tranzakciót, ha tartalmaz legalább egy olyan utasítást, ami módosít legalább két különböző hálózati végpontokon lévő adatbázisokat. A kétfázisú elv biztosítja, hogy elosztott tranzakció minden adatbázisa konzisztens marad, vagyis az összes adatbázis vagy commitálja a tranzakciót, vagy visszagörgeti annak addigi hatásait.

Léteznek ún. autonóm tranzakciók, melyeket más tranzakciók hívnak meg, de azoktól teljesen függetlenül futnak le. A hívást követően a meghívó tranzakció felfüggesztődik, a meghívott tranzakció teljesen független zárakkal és utasításokkal lefut, majd függetlenül attól, hogy committáltunk vagy visszagörgettük a tranzakciót, folytatódik a meghívó tranzakció futása. Ezáltal természetesen létre lehet hozni holtpontot, amit az adatbázis hibaüzenettel ugyan jelez, de ezekért a holtpontokért teljes mértékben az alkalmazás fejlesztője felel. Egy autonóm tranzakció is meghívhat más autonóm tranzakciókat, nincs semmilyen korlát a hívások mélységére. Lehetőség van azonban nem autonóm tranzakciók meghívására is. Ekkor a meghívott tranzació örökli a hívó tranzakció környezetét.


Kapcsolódó link:
Oracle® Database Concepts: Transaction Management

Nincsenek megjegyzések: