Párhuzamos batch futások DB oldali automatizált összehasonlítása

Az IT-vezetőség döntése alapján az IBM zServer mainframe gépeken z/OS és z/Linux operációs rendszer alatt futó összes alkalmazást és kiszolgáló rendszert át kellett telepíteni IBM pSerias RISC szerveren futó AIX operációs rendszert és Oracle adatbázis-kezelőt használó környezetbe.

Bevezetés

A feladat szükségessé tette regressziós tesztelés elvégzését. A regressziós tesztelés a batch folyamatoknak a régi és az új környezetben történő párhuzamos futtatásából és az eredmény összehasonlításából áll.

Az AIX-en futó adatbázis-kezelő megfelelő működését a nagy adatmennyiséget mozgató batch-folyamatok futásával teszteltük. A batch-környezet migrálása a batch-programok tényleges átírását követelte, ezért itt nem módszertani kérdés volt a batch-folyamatok párhuzamos futtatása, majd az eredmények összehasonlítása, hanem sokkal inkább funkcionális és regressziós tesztelés egyidejű elvégzését jelentette.

A fenti konkrét feladaton túlmenően, és ahhoz hasonlóan a jövőben többször is szükség lesz batch-folyamatok összehasonlító tesztelésére, azon belül a táblák összehasonlítására két különböző környezetben végrehajtott futtatás után. Ilyen szituációk lehetnek: archiválás, reorganizáció, Oracle-verzióváltás, a tranzakciós biztosítási rendszer verzióváltása, batch-folyamat lényeges (de a funkcionalitást nem érintő) átírása, batch-alkatrészek változása.

Párhuzamos batch vagy batch-sorozat futását akkor tekintjük ekvivalensnek, ha azonos bemenő adatokra (input) azonos (üzleti, esetleg funkcionális szempontból azonosnak tekinthető) kimenő adatokat (output) produkál. Kimenő adat lehet: file, adatbázistábla, adatbázistábla sora, e-mail, SMS, kinyomtatott papír.

Ebben a cikkben csak az adatbázistáblák adattartalmi azonosságát vagy különbözőségét megállapító, általunk kifejlesztett eszközről lesz szó.

Erre a feladatra kialakítottunk egy meglehetősen általános algoritmust és egy ezen alapuló automata eszközt, mely minimalizálja a manuális tesztelési tevékenységet, és az abból szükségképpen eredő hibákat.

Adatbázisok, tesztelési környezet

A párhuzamos batch-tesztek tesztelési környezetét a következőképpen alakítottuk ki. A batch-futásokat két adattartalmában azonos, de a tesztelendő új elem szempontjából eltérő, az éles rendszernek megfelelő környezeten hajtjuk végre.

A tesztkörnyezetet kiegészítettük egy adatbázissal, melyet a továbbiakban vezérlő adatbázisnak nevezünk. A vezérlő adatbázisból adatbázislinkeket kreáltunk a két tranzakciós rendszer minden adatbázisához. Az összehasonlításokat a vezérlő adatbázisból indítjuk, és ugyancsak ide gyűjtünk adatokat a tranzakciós adatbázisokról a batch-futtatások előtt és után. Ez az adatbázis őrzi a kódgenerálóval készített utasításokat és a teszteredményeket is.

A tranzakciós adatbázisok felületi hozzáférése le van állítva, hogy on-line adatmódosítás a batch-futtatások mellett ne történjen.

A táblaösszehasonlítás

Az adatbázistáblákat a párhuzamos futásokat követően összehasonlítjuk. Természetesen nem az összes táblát, hanem csak az adott futtatási szakaszban érintetteket. Érintettnek nevezzük azt a táblát, amit a batch-futtatás módosít, vagyis amelyre INSERT, UPDATE, DELETE, TRUNCATE, DROP, CREATE hajtódott végre. Azt, hogy a futások során mely táblákat kell összehasonlítani, az ORACLE audit bekapcsolásával nyerjük

Kétféle adatgyűjtést hajtunk végre. Az egyik az ún. üzemi adatgyűjtés, ami arra szolgál, hogy bizonyos táblák összehasonlítása ne a tábla összes sorára vonatkozzon, csak a sorok egy részhalmazára, egy ID-jellegű oszlop szerinti új sorokra. A másikat táblasorszám-gyűjtésnek nevezzük. Ez a releváns sémák tábláiban lévő sorok számának gyűjtését végzi.

Mindkét adatgyűjtés el­menti a gyűjtött adatokat a vezérlő adatbázis egy táblájába. Ezeket az adatokat is használjuk az összehasonlítás­kor. Egyrészt, ha a sorok száma nem azonos, akkor már biztosan hibát találtunk. Másrészt, ha a sorszámok megegyeznek, akkor nem szükséges szimmetrikus differenciát képezni, hanem elegendő az ellenőrző select utasításban a mínusz halmazműveletet csak az egyik irányba elvégezni.

Formalizálva a legegyszerűbb összehasonlító select utasítás a következő. Legyen:

  • DB1, DB2: a vezérlő adatbázis adatbázis linkjei a tranzakciós adatbázisok felé,
  • TABL: az összehasonlítandó tábla neve,
  • COLUMN_LIST: a TABL tábla összehasonlítandó oszlopainak listája
 
SELECT COLUMN_LIST
    FROM TABL@DB1
MINUS
SELECT COLUMN_LIST
    FROM TABL@DB2


Az összehasonlító select utasításokat kódgenerátorral állítjuk elő több okból. Egyrészt a select utasításban lehetnek a táblasorokra vonatkozó futásfüggő megszorítások a gyorsítás érdekében. Másrészt nem feltétlenül hasonlítjuk össze egy tábla összes oszlopát, az ellenőrzendő oszlopokra vonatkozóan változhatnak a szempontok menet közben. Harmadrészt a kódgenerálás csökkenti a manualitást, könnyebben áttekinthetővé teszi az egy-egy szakaszban összehasonlítandó táblák körét.

A kódgenerátorral előállított összehasonlító select utasításokat egy automata futtatja, és az eredményt a vezérlő adatbázis egy táblájába naplózza. Valójában a kódfuttató az összehasonlító select utasítás eredmény sorainak a számát számolja, tehát az alábbit futtatja:

SELECT COUNT(*)
  FROM (SELECT COLUMN_LIST
          FROM TABL@DB1
        MINUS
        SELECT COLUMN_LIST
          FROM TABL@DB2)


Előkészítés: Táblaellenőrzési paraméterek rögzítése

A kódgeneráláshoz szükséges adatokat a vezérlő adatbázis egy adminisztrációs táblájában tároljuk. Itt a tranzakciós adatbázis minden szóba jövő táblájának van egy sora. Egy-egy táblához a következő adatokat tároljuk, frissítjük a futtatási tapasztalatainknak megfelelően:

  • Az összehasonlításból kimaradó, kihagyandó oszlopok listája, például nem hasonlítunk futás időpontját tároló, szekvenciából értéket kapó ID-jellegű adatokat, fájlnév jellegű adatokat. Az itt megadott adatok a COLUMN_LIST oszlop listát befolyásolják.

  • Oszlophelyettesítések listája: ha egy összehasonlítandó oszlop helyett annak egy függvényét kell összehasonlítani. (pl. egy string oszlop helyett annak substringjét), a megadásnál speciális szintaxist használunk, melyet a kódgeneráló dolgoz fel.

  • ID_NAME, MAX_ID_NAME: valamennyi sor összehasonlítása nagy rekordszám és sok oszlop esetén kerülendő. Ha csak újonnan keletkezett sorokat hasonlítunk össze, mert tudjuk, hogy egy táblában a batch-feldolgozás programjai nem törölnek sort és nem módosítanak meglévő sorokat, akkor batch-futás előtt és után mentjük a tábla megfelelő oszlopának (ID-jének) maximális értékét, és csak a batch-futás során keletkezett sorok összehasonlítására szorítkozunk.

  • WHERE_CLAUSE: a sorok szűrésének további feltételét adjuk meg. Korrekt, SQL szintaxist követő feltételt kell megadni, az oszlopneveket prefixelt szintaxis szerint, melyet a kódgeneráló dolgoz fel.

  • Összehasonlítás szükséges-e: flag mely jelzi, hogy egy tábla összehasonlítandó-e. Például kihagyhatunk az összehasonlításból ki nem ürített munkatáblákat.

  • DARABOLO_OSZLOP: nagyméretű táblák esetében az összehasonlítás sokáig tart és óriás méretű TEMP táblaterületet igényel. Gyakran elfogyott a táblaterület. Ennek elkerülésére ezeket a táblákat a tábla egy ID-jellegű oszlopa szerint ID-tartományokra darabolva hasonlítjuk össze, vagyis az összehasonlító select utasítás where feltételéhez hozzátesszük az ID-tartományba esés feltételét. Ebben az oszlopban kell megadni a daraboló ID-oszlop nevét. Előnye még a darabolásnak, hogy hibakereséskor elég egy tábladarabban keresni, nem kell ismét az egész táblát végigolvasni.

  • Darabolás szakasz hossza: Ebben az oszlopban kell megadni a darabolási tartomány méretét.
Ha az ID_NAME, MAX_ID_NAME, WHERE_CLAUSE adatok meg vannak adva, akkor a formalizált összehasonlító utasítás az alábbi:

SELECT COUNT(*)
  FROM (SELECT COLUMN_LIST
          FROM TABL@DB1
         WHERE WHERE_CLAUSE
           AND MAX_ID_NAME értéke batch futás előtt < ID_NAME
           AND ID_NAME <= MAX_ID_NAME értéke batch futás után
        MINUS
        SELECT COLUMN_LIST
          FROM TABL@DB2
         WHERE WHERE_CLAUSE
           AND MAX_ID_NAME értéke batch futás előtt < ID_NAME
           AND ID_NAME <= MAX_ID_NAME értéke batch futás után)


 Párhuzamos batch-futási eredmények összehasonlítása, az összehasonlítás lépései

 Auditálás beállítása
A tranzakciós adatbázis releváns sémáinak tábláira auditálást kell beállítani. A teszt elindítása előtt célszerű a régi audit rekordokat törölni a SYS.AUD$ táblából.

Összehasonlítandó táblák kijelölése

Az adott batch-futásokat követően az audit rekordok alapján összeállítjuk az összehasonlítandó táblák listáját. Ehhez a következő utasítást használjuk:

SELECT DISTINCT OBJ$NAME
  FROM SYS.AUD$
 WHERE ACTION# IN (1, 2, 6, 7, 12, 85)


Az összehasonlítandó táblák nevét, a futás nevet, a szakasz nevet és az összehasonlításhoz szükséges táblaspecifikus adatokat a vezérlő adatbázis egy másik táblájába beírjuk. Ide kerülnek majd az automata összehasonlítás eredményei, és szükség esetén a kézi tesztelés feljegyzései is.

Adatgyűjtés

A batch-programok futása előtt és után végrehajtjuk az üzemi adatgyűjtést és a táblasorszámgyűjtést. A táblasorszámgyűjtés időigényes, a rendszerünkben mintegy 4800 tábla van, ezért több szálon párhuzamosan futtatjuk.

Táblanevek szinkronizálása

Az „Előkészítés: Táblaellenőrzési paraméterek rögzítése” című fejezetben írtuk, hogy a tranzakciós adatbázis tábláira vonatkozó, és az összehasonlításhoz szükséges információkat a vezérlő adatbázis egy táblájában tároljuk és folyamatosan módosítjuk.

Egymást követő batch-sorozatok futásához a tranzakciós adatbázis más és más állapotát töltjük a tesztadatbázisokba. Előfordulhat, hogy a tesztadatbázisban olyan tábla szerepel, amely egyetlen korábbi tesztadatbázisunkban sem szerepelt még, sőt a tesztelés során végrehajtott batch-eljárások is kreálhatnak új táblákat.

A vezérlő adatbázisban lévő táblalistánkat batch-futtatás előtt és után frissítjük, azaz hozzávesszük a tesztadatbázisok új tábláit.

 Összehasonlító select utasítások generálása (kódgenerálás)

Az előző lépésben felvett összehasonlítandó táblákhoz programmal kreálunk összehasonlító select utasítást, és elmentjük a vezérlő adatbázisba. Az összehasonlító select utasítás egyrészt a már korábban felvett táblaspecifikus adatok alapján készül.

Particionált táblák esetében, valamint ha darabolás van specifikálva az adott táblára, a kódgeneráló program egyetlen formális összehasonlító select utasítást generál. Ebbe a kódfuttató program helyettesíti be az Online partíciók nevét (@PARTITION_NAME@), illetve a darabolásnak megfelelő határokat (@LOWERBOUND@ és @UPPERBOUND@), majd lefuttatja az így kapott összehasonlító utasítást.

Particionált tábla esetében szinonimát kell kreálnunk a vezérlő adatbázisban a két tranzakciós adatbázisokban lévő táblára. Ezeket TABL_SYN_DB1, TABL_SYN_DB2-vel jelölve, az összehasonlító utasítás így módosul:

SELECT COLUMN_LIST
  FROM TABL_SYN_DB1 PARTITION(@PARTITION_NAME@)
MINUS
SELECT COLUMN_LIST
  FROM TABL_SYN_DB2 PARTITION(@PARTITION_NAME@)

 
A darabolós összehasonlító utasítás:

SELECT COLUMN_LIST
  FROM TABL@DB1
 WHERE DARABOLO_OSZLOP BETWEEN @LOWERBOUND@ AND @UPPERBOUND@
MINUS
SELECT COLUMN_LIST
  FROM TABL@DB2
 WHERE DARABOLO_OSZLOP BETWEEN @LOWERBOUND@ AND @UPPERBOUND@


Táblaösszehasonlítás automatizált végrehajtása, teszteredmények naplózása

A táblaösszehasonlításokat a kigenerált összehasonlító select utasítások lefuttatásával hajtjuk végre. A kódfuttató program az eredményeket a vezérlő adatbázisba naplózza, kvalifikálva az eredményeket (OK, NOT OK), regisztrálva az eltérések számát, a futás kezdetének és végének időpontját, a futási időt. A program log file-ba és a DBMS_OUTPUT-ra is ír, e-mailt és SMS-t küld az eljárás befejeztekor, illetve a táblák bizonyos százalékának megvizsgálásának befejezésekor.

Táblaösszehasonlítás manuális végrehajtása, teszteredmények naplózása

Azon táblák, melyeknél a különbséghalmaz rekordjainak a száma nem nulla, manuális vizsgálatot igényelnek. A manuális tesztelés eredményét is az automata összehasonlító által használt tábla erre a célra szolgáló oszlopaiba jegyezzük be. 

Szerző:
Angyal Tibor, Hoffer János

<< Vissza