Migráció IV.

Tranzakciókezelés

Microsoft SQL Server 2000 alatt három féle módon lehet tranzakciót kezdeni:
  • explicit módon: egy BEGIN TRANSACTION utasítás kiadásával
  • implicit módon: amennyiben a SET IMPLICIT_TRANSACTIONS ON utasítással bekapcsoltuk ezt a módot, akkor az ezt követő utasítás automatikusan egy tranzakciót fog nyitni. Amikor az befejeződik, akkor a következő utasítás egy új tranzakciót kezd, és így tovább.
  • autocommit: ez az alapértelmezett mód az SQL Server-ben: minden egyes T-SQL utasítás vagy véglegesítésre kerül (commit), vagy visszagörgetődik (rollback).

Explicit tranzakciók esetén a programozó határozza meg a tranzakció elejét és végét is, Transact-SQL scriptek esetén BEGIN TRANSACTION / COMMIT / ROLLBACK utasításokkal, ADO.NET esetén pedig az SqlConnection objektum BeginTransaction() illetve Commit() / Rollback() metódusaival.

A BEGIN TRANSACTION utasítás 1-el növeli a @@TRANCOUNT változó értékét (alapesetben a változó 0), a COMMIT 1-el csökkenti, míg a ROLLBACK 0-ra állítja. Ez azért van így, mert SQL Server alatt úgy lehet tranzakciókat egymásba ágyazni, hogy a beágyazott tranzakciók esetében az adatbázis a COMMIT utasításokat figyelmen kívül hagyja, csak a legkülső COMMIT után lesznek a módosítások véglegesítve. A ROLLBACK utasítás viszont minden aktív tranzakciót visszagörget.

Ezzel szemben Oracle adatbáziskezelő alatt egy tranzakció az első végrehajtható SQL utasítással kezdődik, és vagy akkor ér véget, amikor explicit módon kiadunk egy COMMIT illetve ROLLBACK utasítást, vagy implicit módon, pl.: egy DDL utasítás végrehajtásával, vagy az adatbázisból történő kilépéskor (disconnect).

Léteznek még úgynevezett autonóm tranzakciók (autonomous transactions), amik teljesen függetlenek a "hívó" tranzakciótól. Például, ha egy tárolt eljárás az AUTONOMOUS_TRANSACTION direktívával lett lefordítva, akkor, amikor meghívódik egy külső tranzakcióból, nem látja annak a még nem véglegesített adatait, illetve tőle függetlenül lesz véglegesítve vagy visszagörgetve. Ez például naplózást megvalósító eljárások esetén lehet hasznos.

Az Oracle Migration Workbench a BEGIN TRANSACTION utasításokat a SET TRANSACTION READ WRITE utasítássá fordítja át, ami az aktuális tranzakciót úgy állítja át, hogy utasítás szintű konzisztenciát biztosítson (statement-level read consistency).

Ez annyiban nem szerencsés, hogy míg a BEGIN TRANSACTION tetszőleges helyen szerepelhet egy T-SQL blokkban, addig Oracle alatt a tranzakció tulajdonságait csak az első utasításban lehet beállítani. Azaz például, ha egy INSERT szerepel a BEGIN TRANSACTION előtt (az explicit tranzakción kívül, alapértelmezetten autocommit módban), akkor ezt a Migration Workbench segítségével PL/SQL-re fordítva valami ilyesmit kapunk:

CREATE OR REPLACE PROCEDURE sp_something
AS
BEGIN
INSERT INTO proba
VALUES ( 1, SYSDATE );

SET TRANSACTION READ WRITE;

INSERT INTO proba
VALUES ( 2, SYSDATE );

ROLLBACK;

END;

ami - habár szintaktikailag helyes, azaz le fog fordulni - futáskor hibát fog adni:

ORA-01453: SET TRANSACTION must be first statement of transaction

Gond van még a @@TRANCOUNT változóval is, mert a dokumentáció szerint hiába támogatja a Migration Workbench a globális változók migrációját, nekem összesen annyit sikerült elérnem, hogy a @@TRANCOUNT-ot v_transcount-ra cserélte. A SwisSQL (a Migration Workbench konkurrenciája) ezt a kérdést úgy oldja meg, hogy egy package-ben deklarál egy változót, amit minden egyes tranzakciókezelő utasításkor növel/csökkent, azaz BEGIN TRANSACTION helyett növeli eggyel, COMMIT után csökkenti eggyel, és ROLLBACK után pedig 0-ra állítja.

0 megjegyzés: