Delphi - Tranzakció-kezelés az MS SQL-ben

Transact SQL 26. rész

forráskód letöltése
A tranzakciók segítségével több módosítást végezhetünk el az adatbázisban úgy, mintha egyetlen művelet lenne. Az elvégzett módosítások nem kerülnek azonnal végrehajtásra, csak akkor, amikor erről külön rendelkezünk, de megoldható a tranzakció ún. visszagörgetése, amellyel eldobjuk a módosításokat, és a tranzakció előtti állapotot állítjuk vissza. A tranzakciók használata nagyobb biztonságot ad, sőt, több felhasználós rendszereknél elengedhetetlen.
A tranzakciókkal szemben négy fontos követelmény van:
Atomiság (Atomicity)
Két eset lehetséges: a tranzakció vagy befejeződött, vagy nem. Ez annyit jelent, hogy a tranzakcióban végrehajtott műveleteknek vagy mindegyike, vagy pedig egyike sem hajtódik végre, vagyis vagy minden műveletet végrehajtunk, vagy egyet sem.
Következetesség (Consistency)
A tranzakció végrehajtása után az adatbázisnak olyan állapotba kell kerülne, ahol nincs semmi függőben, a tranzakcióban elvégzett összes műveletnek befejezettnek kell lennie.
Elkülönítés (Isolation)
A tranzakció nem függhet más tranzakcióktól, és nem is lehet hatással más tranzakciókra.
Tartósság (Durability)
A tranzakcióban elvégzett műveletet a tranzakció befejezése után már nem lehet visszavonni, meg nem történté tenni. Az összefüggő műveleteket ezért szokás egy tranzakción belül végrehajtani, így biztosíthatjuk, hogy vagy mindegyik művelet végrehajtódik, vagy egyik sem.
Ezek a tulajdonságok, szabályok nem garantáltak, a programozónak kell ezekre figyelnie. Ha bármelyik szabály megdőlne a programozás során, akkor újra át kell gondolni a feladatot.
A tranzakciókat egy-egy végrehajtandó feladatként értelmezhetjük, ami egy, vagy több SQL utasítást tartalmaz. A tranzakciók egymásba is ágyazhatók. Minden megkezdett tranzakcióhoz kell, hogy tartozzon egy COMMIT TRAN vagy egy ROLLBACK TRAN utasítás. A COMMIT TRAN utasítással véglegesíthetjük a módosításokat, míg a ROLLBACK TRAN utasítással eldobjuk azokat. A TRAN itt is csak rövidítés, ha akarjuk kiírhatjuk a TANSACTION szót is. Ha a COMMIT TRAN és ROLLBACK TRAN utasítások után nem adjuk meg a tranzakció nevét, akkor az utolsó megkezdett tranzakcióra fognak vonatkozni.
A COMMIT TRAN helyett használhatjuk a COMMIT WORK utasítást is, sőt a WORK-öt ebben az esetben el is hagyhatjuk. Ennek hátránya, hogy nem adható meg a tranzakció neve (csak az SQL-92 kompatibilitás miatt létezik). A COMMIT WORK párja a ROLLBACK WORK, amit a ROLLBACK TRAN helyett használhatunk. Ugyanaz vonatkozik rá, mint a COMMIT WORK-re, tehát a WORK kulcsszó elhagyható, és a tranzakció neve nem adható meg.
A példaprogramban létrehozunk egy teszt adatbázist (01.sql), benne egy táblával, amit feltöltünk néhány rekorddal (02.sql).
03_BEGIN_TRAN.sql
Az ebben a fájlban tárolt SQL utasítással kezdünk el egy új tranzakciót. Az utasítás a BEGIN TRANSACTION, vagy rövidítve BEGIN TRAN, ennek formátuma a következő:
BEGIN TRAN[SACTION] [transaction_name [WITH MARK [’description’] ] ];
A szögletes zárójelek közötti részek opcionálisak, használatuk nem kötelező. A BEGIN TRAN után adhatunk egy nevet is a tranzakciónak, amit később a COMMIT vagy ROLLBACK utasításoknál használhatunk a tranzakció azonosítására. A nevet megadhatjuk char, varchar, nchar, vagy nvarchar típusú változóval is.
A WITH MARK kapcsoló megadásával azt érhetjük el, hogy a tranzakcióban elvégzett műveletek végelegesítése után is visszaállítható lesz a tranzakció előtti állapot. A kapcsoló használata csak akkor lehetséges, ha a tranzakciónak nevet is adtunk. A WITH MARK kapcsoló után egy rövid megjegyzést is írhatunk.
A 03_BEGIN_TRAN.sql fájl tartalma:
USE TransactionTest;
BEGIN TRANSACTION TEST_TRAN;
SELECT 'Tranzakció indul';
04_MODIFY.sql
Az ebben a fájlban tárolt SQL utasítások különböző módosításokat végeznek el a teszt tábla adatain.
USE TransactionTest;
UPDATE TestTable SET C = C * 1.8 WHERE C<30;
INSERT INTO TestTable (B,C,D) VALUES ('NEW', 1.0, '2002.10.01');
SELECT * FROM TestTable;
05_COMMIT.sql
Ezekkel az SQL utasításokkal véglegesítjük a 04_MODIFY.sql scriptben elvégzett módosításokat. Ha ezt futtatjuk, akkor utána a 06_ROLLBACK.sql scriptet már ne futtassuk, mivel az hibához vezet.
USE TransactionTest;
COMMIT TRANSACTION TEST_TRAN;
SELECT * FROm TestTable;
06_ROLLBACK.sql
Ha nem akarjuk a 04_MODIFY.sql script-ben elvégzett módosításokat rögzíteni, akkor a 06_ROLLBACK.sql scriptet futtassuk le. Ezzel lezárjuk a tranzakciót úgy, hogy az elvégzett módosítások nem kerülnek véglegesítésre, a tranzakció előtti állapot lesz érvényes.
A 07.sql script-ben töröljük a teszt adatbázist.
Próbáljuk ki a következőket (miután létrehoztuk az adatbázist és a teszt táblát a 01.sql és 02.sql scriptekkel):
  • indítsuk el a tranzakciót (03_BEGIN_TRAN.sql), majd futtassuk a 04_modify.sql scriptet (akár többször is egymás után). Ezután futtassuk a 05_COMMIT.sql script-et, mivel véglegesítjük az adatokat;
  • indítsunk megint egy tranzakciót, futtassuk a módosításokat megint, majd futtassuk a 06_ROLLBACk.sql script-et.
  • futtassuk a módosításokat a tranzakció indítása nélkül.

Transact SQL cikksorozat