MySQL mindenkinek 9

A relációs adatbázisok előnyei közül ma a tranzakciókezelést szolgáljuk fel ebédre. Egy tranzakció tulajdonképpen egy nagy tányér SQL művelet amelyeknek csak együtt van értelme. Tipikus példa erre egy banki átutalás, amelynek során (jó esetben) az egyik számla egyenlegét akkor csökkentjük amikor a másikét növeljük.

Kicsit részletesebben egy banki átutalási művelet a következő lépésekből állna össze:

  • Állapítsuk meg, hogy a cél “B” számla létezik-e
  • Keressük ki az “A” (átutaló) számlát és állapítsuk meg az egyenlegét
  • Ha az egyenleg nagyobb mint az utalandó összeg akkor csökkentsük az egyenleget
  • “B” számla egyenlegéhez adjuk hozzá az összeget

Persze a valós életben ennél kb 25-ször több lépés zajlik le de a példánk szempontjából ez is elegendő.

Az átutalási művelet – azaz a tranzakció – csak akkor értelmezhető ha minden lépés végrehajtható egymás után. Egy ilyen műveletnél nem engedhető meg, hogy mondjuk az utolsó lépés nélkül végrehajtódjon az első három.

Az ilyen összecsomagolt műveletek együttes végrehajtására adnak lehetőséget a tranzakciók. Tranzakciók használatához egyenlőre a MySQL kizárólag az InnoDB táblatípust támogatja.

Az elv

A tranzakciók elve szerint a MySQL fogja szépen az összecsomagolt SQL műveleteket és elkezdi szépen sorban végrehajtani őket. Amennyiben minden rendben zajlik akkor véglegesíti a tranzakciót, és ebben a pillanatban kerülnek a tényleges módosítások az adattáblákba.

Amennyiben a tranzakció során bárhol hiba képződik, vagy mondjuk leáll a szerver akkor a tranzakció nem lesz végrehajtva, hanem a lépések visszavonásra kerülnek.

A gyakorlat

A gyakorlatban a fenti példa a következőképpen nézne ki egy php program keretében:

<?php

$utaltOsszeg = 500;

//célszámla kikeresése
$e = mysql_query("SELECT id FROM bankszamlak WHERE szamlaszam = '12345678-12345678'");
$celszamla = mysql_fetch_row($e);

//az indító számla egyenlege elegendő az utaláshoz?
$e = mysql_query("SELECT id, egyenleg FROM bankszamlak WHERE szamlaszam = '87654321-87654321'");
$utalo = mysql_fetch_array($e);

if($utalo['egyenleg'] >= $utaltOsszeg){
   //ha elegendő az egyenleg vonjuk le belőle
   //tranzakció indítása
   mysql_query("START TRANSACTION");
   mysql_query('UPDATE bankszamlak SET egyenleg = egyenleg-' . $utaltOsszeg . ' WHERE id = ' . $utalo['id']);

   //adjuk hozzá a célszámla egyenlegéhez
   mysql_query('UPDATE bankszamlak SET egyenleg = egyenleg+' . $utaltOsszeg . ' WHERE id = ' . $celszamla[0]);

   //eddig minden rendben hajtsuk végre a tranzakciót
   mysql_query('COMMIT');
}
?>

A fenti kód hatására ami egyből látszik az az, hogy ha nincs elegendő pénz akkor a tranzakció nem hajtódik végre. Persze eddig nem nyertünk semmit, ezt tisztán PHP-val is megtehettük volna tranzakciók nélkül. Ami ebből a kódból nem látszik, de történik mondjuk abban az esetben ha menet közben van egy áramkimaradás, megszakad a kommunikáció, vagy például megszűnik a fogadó számla pont ebben a pillanatban, az hogy COMMIT hiányában nem hajtódik végre a tranzakció. Ez azért van így mert a tranzakció alatt előforduló bármilyen hiba automatikusan meghívja a ROLLBACK eljárást.

Nem akarok jobban belebonyolódni a tranzakciók témájába, akit érdekel talál róla elegendő információt a neten, ízelítőként pedig ennyi is elég.

Jó kódolást!

4 thoughts on “MySQL mindenkinek 9

  1. hella,
    Te a fizetős verziót használod? nekem sehogy sem sikerült összehozni hogy a linkelt mezőket kösse össze a vonal, és ne csak a tábla közepére mutasson

    • Nem a linkelt mezőket köti össze hanem a táblákat. Ez normális. Némileg bonyolultabb lenne a vonalak megjelenítése ha a mezőket kötné össze. Képzeld el ha pl két tábla kapcsolatban van és az ábrán egymás alá teszed őket. Hogy mennének akkor a vonalak?

  2. MySQL Workbench 5.1.5 Alpha/GPL
    Igen, táblákat kapcsolunk össze, nem mezőket. Miután az eszköztáron kiválasztottuk a kapcsolat típusát, katt az egyik, majd a másik táblára. A szükséges idegen kulcsok (foreign key) automatikusan létrejönnek. (Helyesen mondom tanár úr?) A kapcsolat fölé húzva az egeret jelzésre kerül, hogy a kapcsolt táblák mely mezői között áll fent a kapcsolat.

Vélemény, hozzászólás?

Az email címet nem tesszük közzé. A kötelező mezőket * karakterrel jelöljük.