Konkurens batch taszk kérdés

13 views
Skip to first unread message

Tisch Dávid

unread,
Sep 22, 2017, 5:33:28 AM9/22/17
to magic-...@googlegroups.com

Kedves Kollégák!

Adódott egy olyan feladat, amikor konkurens batch taszkokkal kéne egy adattáblát feldolgozni. Az lenne a kérdésem, hogy - tapasztalatotok szerint - mit történik akkor, ha a range feltétel szerint egy adott rekord mind a kettő batch taszk adatnézetébe bekerül, de az egyik előbb dolgozza fel azt (fizikai tranzakció, lockolással egybekötött tranzakció indítás, azonnali lockolás, recover hibakezelési mód), és a feldolgozás során kitölt egy olyan adatmezőt, ami miatt az adott rekordot a másik taszknak már át kéne lépnie?

Például mindkét taszk arra szűr, hogy csak a meg nem jelölt rekordokon fusson végig. Az egyik elkap egy rekordot, lockolja, a másik odaér és vár. (Tényleg vár?) Az egyik megjelöli a rekordot, aztán elengedi azt és lép a következőre.

Mi történik ez után? A másik taszk - érzékelve, hogy a rekord legújabb állapota szerint már nem tartozik az adatnézetbe - átlépi azt? Vagy - mivel eredetileg belekerült a SELECT eredményhalmazába - mindenképpen fel akarja dolgozni azt?

Válaszotokat előre is köszönöm!
Üdvözlettel:

Dávid


CsP

unread,
Sep 25, 2017, 10:00:39 AM9/25/17
to Magic Support Levelezőlista
Szia Dávid,

Milyen adatbáziskezelővel próbálkozol? 

Talán máshonnan kellene megközelíteni a problémát. A konkurens taszkok ne egy megadott 'range'-en fussanak, hanem mindig kérjenek egy következő feldolgozandó rekord ID-t egy közpotni 'szemafor' programtól. Pont mint a 'központi sorszámosztó', csak nem új rekord keletkezik, hanem a duplán feldolgozást előznéd meg. Ha valahol elakad a feldolgozás, (de így nem fog) vissza kell dobni a feldolgozandó rekord ID-t a szemafornak és az majd újra kiosztja.

Így attól se kell tartani, hogy más adatbáziskezelő alatt hibázna a lock-olás.

CsP

Tisch Dávid

unread,
Sep 25, 2017, 10:33:27 AM9/25/17
to magic-...@googlegroups.com

Szia Péter!

Köszi a választ! Ez a megoldás vélhetően jó, amit írsz. Én most egyelőre azt csináltam, hogy a batch program rekord suffixét egy feltétel blokkba teszem, hogy csak akkor fusson le, ha a flag mező még nincs beállítva. Az érdekelne nagyon, hogy vajon erre szükség van-e? (Félek tőle, hogy igen.) Egyébként SQL Server 2016 Express-ről van szó.

Üdvözlettel:

Dávid

CsP

unread,
Sep 26, 2017, 2:38:26 AM9/26/17
to Magic Support Levelezőlista
Szia,

inkább az a gond, hogy ha ragaszkodsz a sima tartományozáshoz a konkurens batch-ekben, akkor ahogy nő a feldolgozandó adatmennyiség és gondolom a konkurens feldolgozó taszkok száma, egyre több lesz az 'összeakadás', a fel nem dolgozott rekord. Értem, hogy a következő körben majd beleesik a feldolgozási tartományba, de mindig lesz felesleges futás (ahol nem kerül már rögzítésre a rekord, mert közben feldolgozódott).
Ha ütemezőt, szemafort használsz nem lesz felesleges futás, minden 'megfogott' rekord feldolgozható.
Hátránya, hogy több DB kérés lesz a gateway-en keresztűl, több, de kisebb adatnézetet kap vissza a Magic az adatbázis-kezelőtől feldolgozásra

Végiggondolva ha a jelölő flag (amit a feldolgozás jelzésére használsz) ugyanabban a feldolgozandó rekordban van amin dolgozik a taszkod, akkor rekord szintű tranzakció kezelést kell csinálnod, hogy rögtön visszaíródjon a feldolgozás jelzés, így viszont már sebességben nem lesz sokkal gyorsabb, mintha a taszkod eleve 1 rekordon dolgozna. 

Szvsz csináld meg mindkét módon és írd meg a tapasztalatod!

P

Bakos Gyula

unread,
Sep 26, 2017, 3:07:00 AM9/26/17
to magic-...@googlegroups.com

Szia Dávid,

 

Én is a Péter által említett megoldást javasolnám, mi is ezt használjuk hasonló esetekben.

A mi esetünkben van még egy oka ennek, mégpedig az, hogy mi Oracle adatbázis kezelőt használunk, és az szeret „fetch out of sequence” hibaüzenetet dobni (uniPaaS és xpa 3.x is), ha olyan Magic batch taszkot írunk, ami több rekordra szűr pl. egy feldolgozva flag-re, és a rekord utóban módosítja is azt, illetve hasonló a helyzet rekord szintű tranzakció esetén is. Szóval nálunk a „sima tartományozás” módszer semmiképpen sem jöhetne szóba ilyen esetben. Hogy SQL szervernél van-e hasonló probléma, azt nem tudom.

 

Még egy dolog, azt írod:

Én most egyelőre azt csináltam, hogy a batch program rekord suffixét egy feltétel blokkba teszem, hogy csak akkor fusson le, ha a flag mező még nincs beállítva.”Ez szerintem még mindig nem lenne neked elég, mert ilyenkor a Magic a kifejezés kiértékeléséhez nem kéri el az adatbáziskezelőtől újra az adott mező értékét. Ezt a gateway log bekapcsolásával ellenőrizheted, törésponttal állítsd meg az adott block előtt a feldolgozást, és ha átlépsz az adott utasításon, akkor nem fog a Magic fetch utasítást írni a gateway logba. Úgyhogy itt csak egy call subtask menthetné meg a helyzetet, amiben Link utasítással ismét ráolvasol a kérdéses rekordra, Cache=No-val. Ezzel együtt szerintem az első megoldással sok későbbi problémától kíméled meg magadat.

 

Üdvözlettel:

Bakos Gyula

SZEGED Software Zrt.

--
Azért kapta ezt az üzenetet, mert feliratkozott a Google Csoportok „Magic Support Levelezőlista” csoportjára.
Az erről a csoportról és az ahhoz kapcsolódó e-mailekről való leiratkozáshoz küldjön egy e-amailt a(z) magic-suppor...@googlegroups.com címre.
Ha üzenetet szeretne küldeni ebbe a csoportba, küldjön e-mailt a(z) magic-...@googlegroups.com címre.
A csoportot a(z) https://groups.google.com/group/magic-support címen keresheti fel.
További lehetőségekért látogasson el ide: https://groups.google.com/d/optout.

Tisch Dávid

unread,
Sep 26, 2017, 5:35:44 AM9/26/17
to magic-...@googlegroups.com

Kedves Gyula! Kedves Péter! Kedves Kollégák!

Bár az idő eléggé szorít, mégsem maradt már hátra, mint kipróbálni, amire Gyula és Péter is biztatott. Ennek eredményét szeretném megosztani Veletek.

Először is magáról a feladatról néhány szót: bizonyos felhasználói interakciók hatására párhuzamos batch taszkok indulnak, akik fel akarják dolgozni egy tábla kevés számú, még fel nem dolgozott (néhány 10 db) rekordját. Egy munkaállomáson csak 1-1 ilyen taszk fut, de a több munkaállomás miatt előfordulhatnak párhuzamos feldolgozások. A cél, hogy megakadályozzuk, hogy egy rekordra véletlenül kétszer fusson le egy ilyen feldolgozás.

A feladat teszteléséhez felvettem egy táblát, amelynek 2 mezője volt: egy auto növekvő kód és egy numerikus flag. A táblán 1 db 2 szegmenses index volt: flag ASC, kód ASC. 10 rekordot vettem föl a táblába.

Ezek után készítettem 2 batch taszkot. Mindkettő ugyanazon a táblán futott végig, azokra a rekordokra range-elve, ahol a flag 0. "A" taszk felülről lefelé futott végig a rekordokon és a flag-et 1-re állította, "B" taszk alulról felfelé futott végig a rekordokon és a flag-et 2-re állította. Mindkét taszk 2 mp-et várt minden rekord utóban. Fizikai tranzakciót használtam, lockolással együtt indított tranzakcióval, azonnali lockolással és recover hibakezelési stratégiával. "B" párhuzamos taszkot "A" indította a taszk prefixében.

Azt tapasztaltam, hogy az első 5 rekordban 1 lett a flag értéke, a második 5-ben pedig 2, miközben "A" és "B" taszk is a feldolgozás második felében 5-5 db "record has been changed by another user" hibát dobott. Ugyanez volt az eredmény akkor is, ha a rekord utóban update előtt ellenőriztem a flag értékét. Vagyis a range által visszaadott rekordokon - eredeti adattartalommal - mindenképpen végig ment mind a kettő, emellett viszont azt azért észre vették, ha valaki azt a rekordot már módosította, és az ilyen rekordokat eldobták. Ha mindehhez egy üres "Record changed by another user" hiba esemény figyelőt is felvettem mindkét taszkba, ignore hibakezelési stratégiával, akkor - azonos eredmény mellett - a hibaüzeneteket is megúsztam.

Szóval ezek szerint nem muszáj (nekem) egyesével foglalnom a kordokat, de a flag értékét teljesen fölösleges vizsgálnom, és fel kell vennem egy hibakezelőt, hogy ne legyen futási hiba. Egyet értetek ezzel?

Előre is köszi a válaszokat!
Üdvözlettel:

Dávid

Bakos Gyula

unread,
Sep 26, 2017, 6:44:04 AM9/26/17
to magic-...@googlegroups.com

Szia,

 

Természetesen egy program akkor „jó”, ha a megfelelő teszteken sikeresen átesett, így jó lehet a te megoldásod is, ha a tesztek után megfelelőnek ítéled.

A következőket azonban hozzátenném:

  • Itt a 2 batch taszkot ellentétes rendezés szerint indítottad a táblára. Nálunk a legtöbbször igény, hogy a feldolgozandó rekordokat az érkezésük sorrendjében kell feldolgozni. Kérdés, mit mutatna a módszered, ha mindkét taszk ugyanabban a sorrendben dolgozná fel a rekordokat. Vagy ez nálad nem szempont?
  • Jelen esetben a Magic-re bíztad a problémás esetek lekezelését. Én jobban szeretem, ha a kód úgy van megírva, hogy az a logikából következően működjön jól.
  • Akár kettőnél több munkaállomás is elindíthat ilyen párhuzamos taszkot? Akkor érdemes lenne 2-nél több szállal is kipróbálni. Ebben az esetben azok a szálak is végigolvassák az összes feldolgozható rekordot, amelyek végül akár egyetlen rekord feldolgozását sem végezhetik el.

 

Üdv: Gyula

--

Peter Csillag

unread,
Sep 26, 2017, 7:28:36 AM9/26/17
to magic-...@googlegroups.com
Sziasztok,

szerintem rengeteg féle módon meg lehet oldani a feladatot (is), az én korábbi szívásaim, tapasztalataim mondatták (íratták) az első levelemet, melyben javasoltam, hogy pont ne a Magic-re bízd a konkurens foglalások kezelését. Nyilván meg lehet oldani így is és ha nem változnak az adatok, környezetek, felhasználói szokások, egyéb feltételek, akkor az jó is lesz. De ha több adat, több szál, más adatbázis, mittomén változás lesz, újra lehet hangolni (lekezelni az új hibaüzeneteket, keresni az 'átlépett' rekordot, stb) az egészet. 

A megoldásod tök jó a mostani, pontosan körülírt esetre, ha azonban bármi változás történik, lehet piszkálgatnod kell a batch-eket. 

P

Ui.: Kényszer, hogy munkaállomásokon futnak ezek a párhuzamos taszkok? Tipikusan szerver feladat lenne, több szálon indítva. Még kevesebb gondod lenne...


--
Azért kapta ezt az üzenetet, mert feliratkozott a Google Csoportok „Magic Support Levelezőlista” csoportjára.
Az erről a csoportról és az ahhoz kapcsolódó e-mailekről való leiratkozáshoz küldjön egy e-amailt a(z) magic-support+unsubscribe@googlegroups.com címre.

Tisch Dávid

unread,
Sep 26, 2017, 11:18:20 AM9/26/17
to magic-...@googlegroups.com

Szia Gyula!

Köszi a válaszodat! Ha a két taszkot azonos sorrendben szalajtom végig a rekordokon (az elején ilyen volt a teszt, mert elszúrtam az indexet :) ), akkor minden rekordba 1-es kerül a végén, a "B" taszk meg kb. 7 hibát dob. (Nyilván az indítási késleltetés miatt.)

Teljesen egyetértek a kódszervezési megjegyzéseiddel! Ha lesz időm, majd átírom az enyéimet is. A probléma tulajdonképpen marginális, ritkán és kevés adattal fordulhat csak ilyen elő, desktop környezetben, csak a hiba lehetőségét kell kizárni. (Értem, hogy pont attól válik az egész bizonytalanná, hogy a Magic kezeli le a hibát. :) Igyekszem majd algoritmikusan védekezni.)

Üdv:

Dávid

Tisch Dávid

unread,
Sep 26, 2017, 11:27:09 AM9/26/17
to magic-...@googlegroups.com

Szia Péter!

Köszi a válaszodat! Ahogy Gyulának írt válaszomban is írtam: alkalom adtán igyekszem átszervezni majd a kódot.

A helyzet az, hogy november 1-étől minden háziorvosnak csatlakoznia kell az eEgészségügyi felhőhöz, ami azt jelenti, hogy bizonyos dolgok megtörténtéről jelentést kell küldeni valós időben. Ha ez valami miatt meghiúsul (nincs internet, nincs ott jogosult személy, nem elérhető a felhő, stb.), akkor ezeket az eseményeket naplózni kell és alkalom adtán újra be kell küldeni őket.

A kommunikáció gerincét egy szerveren futó PHP wrapper kódom viszi, nekem "csak" azzal kéne kommunikálnom, de úgy látom, hogy a Magic-et nem arra a feladatra tervezték, hogy képernyő nélküli, aszinkron batch taszkokból nagy hibatűrésű, szükség esetén "hibajavító" módon működő back end rendszert írjanak benne. Úgyhogy most a lehetőségek a szükségek és a határidő szorításában vergődve született ez a megoldás, ami - mint kiderült - működik, de lehet, hogy nem a legjobb. Ha még élek november 1-e után, akkor átírom a kódot. :)

Üdv és köszönet:

Dávid

Bakos Gyula

unread,
Sep 26, 2017, 11:36:33 AM9/26/17
to magic-...@googlegroups.com

Marci azt mondaná, tipikus xpi-s feladat… 😊

Gyula

 

From: magic-...@googlegroups.com [mailto:magic-...@googlegroups.com] On Behalf Of Tisch Dávid
Sent: Tuesday, September 26, 2017 5:27 PM
To: magic-...@googlegroups.com
Subject: Re: [Magic Support] Re: Konkurens batch taszk kérdés

 

Szia Péter!

--

Azért kapta ezt az üzenetet, mert feliratkozott a Google Csoportok „Magic Support Levelezőlista” csoportjára.

Az erről a csoportról és az ahhoz kapcsolódó e-mailekről való leiratkozáshoz küldjön egy e-amailt a(z) magic-suppor...@googlegroups.com címre.

Tisch Dávid

unread,
Sep 27, 2017, 2:27:59 AM9/27/17
to magic-...@googlegroups.com

:D És ha nem, akkor is. ;)

Ámor Kalo

unread,
Sep 28, 2017, 4:53:29 AM9/28/17
to magic-...@googlegroups.com
Szia Dávid és többiek!

Bocs, hogy ilyen későn... látom, hogy nagyjából lezajlott a beszélgetés, csak némi okoskodást szeretnék hozzáfűzni. :-)
Én alapvetően nagyon szeretném a Magic-et ily módon használni, ahogy Dávid leírta. Szerintem a Magic alapvetően úgy is lett tervezve, hogy ilyen párhuzamos-azonos tartományos-feldolgozásos helyzetet kezeljen. Az adatbáziskezelő meg lockoljon, az a dolga. Általában nem is az adatbáziskezelőkkel van baj ebben a kérdésben, hanem a Magic-es gateway-ek vannak szarul megírva. Jelenlegi tudásom szerint ez az alábbiak szerint néz ki:

Lockolás van és 99,99%-ban jól működik:
Pervasive Btrieve
Oracle
DB2
Lockolás történik de számos esetben rosszul működik:
MSSQL
Lockolás NINCS, zéró, nope:
Pervasive SQL
MySQL
bármilyen ODBC
SQLite nyilván

(MySQL-re elvben meg fogják csinálni, legalábbis nekünk megígérte az MSE.)

Tehát Dávid amit szeretnél azt Btrieve, Oracle és DB2 alatt meg lehet valósítani, elég nagy biztonsággal. Másban nem ajánlott. Még ezeknél is nagyon kell vigyázni, hogy ha a batch folyamatot egy másik batch vagy online hívja, amely nem megfelelően van beállítva, akkor a Magic elkezd okoskodni, magasabb (korábbi) szinteken kezd el lockolni, tranzakciózni. Szerintünk ebből jön a Gyula által is említett Out of Sequence pl. Oracle alatt. Mit jelent a nem megfelelően? Ha előtte a hívási fában van legalább egy olyan program, mely bármikor tranzakciót nyit, Módosítás módban van, Írásra van nyitva egy tábla, még ha program maga egyetlen rekordot sem módosít, akkor a Magic kitalálja hogy lesz jó. Hát nem úgy. :-)

Engem általában elfog a rettegés, ha meglátok egy "a Rekordot más felhasználó módosította" üzenetet. Tapasztalataink szerint ez az általános jele annak, hogy a lockolás nem sikerült, ez a rekord ki lett hagyva. Rosszabb esetben a futás is megszakadt, vagy konzisztenciális probléma keletkezett.

Ezen felül viszont egyet kell értsek a többiekkel. Különösen abban az esetben, amikor a kérdéses táblát más (nem Magic) is módosíthatja, az ideális megoldás, hogy egyetlen rekordot dolgozok fel, nem egy tartományon futok végig. Sőt! Mostanában ezt odáig fokoztuk, hogy átállítunk egy állapotot, hogy megkezdjük a feldolgozást, beállítjuk, hogy melyik szálon, majd következő lépésben, már erre az állapotra szűrve dolgozzuk fel az adott tételt, és ha minden sikeres akkor állítjuk feldolgozottra. Bizony rekordonként, bizony kétszerre, bizony sokkal lassabban. Gáz, de ha a konzisztencia fontos, akkor ez a jó megoldás. A Magic kényszerít erre.

Nem ijesztgetni akarok bárkit, de szeretném felhívni a figyelmet arra, amit Gyula is írt: 2 szálon elvégzett teszt nem biztos, hogy teszt, csak akkor ha megelégszel azzal, hogy kb. 99,99%-ban fogod lockolni a rekordokat. Találkoztunk olyan esetekkel, ahol 3 párhuzamos szál nem okozott problémát, 30 viszont igen. Labor körülmények között minden ment, amikor 100-150 felhasználó lockolt-tranzaktált össze-vissza, akkor itt-ott, egy-egy rekord kimaradt, nem módosult. Nem volt rá magyarázat, hiába ismételgettük a teszteket. Csak azt tudtam mondani it's Magic. Ezzel persze nincs semmi baj, ha a rendszert így építjük fel nulláról. Ha törekszünk, hogy a rekordok 100%-át feldolgozzuk, de tudjuk, hogy úgy se fog sikerülni. ;-)

Többek között ez is hozzájárult, hogy 30 év után, tudatosan elkezdtem leépíteni a Magic-et és más vizekre próbálok evezni, de ez már egy másik történet. ;-)

Szép napot, jó munkát, Mindenkinek!

Ámor


--
Azért kapta ezt az üzenetet, mert feliratkozott a Google Csoportok „Magic Support Levelezőlista” csoportjára.
Az erről a csoportról és az ahhoz kapcsolódó e-mailekről való leiratkozáshoz küldjön egy e-amailt a(z) magic-support+unsubscribe@googlegroups.com címre.

Tisch Dávid

unread,
Sep 29, 2017, 3:44:18 AM9/29/17
to magic-...@googlegroups.com

Szia Ámor!

Köszi a választ! Sejtettem, hogy van a kollektív tudatban sok minden a témával kapcsolatban. :)

Az Általad mondottakhoz én annyit tennék hozzá, hogy mi az SQL Server-es átállás kapcsán majdnem elveszítettük a teszt felhasználónkat, pedig a teszt időszak alatt ingyen használta a programot, annyi problémánk volt az Általad is említett kalóz tranzakció kezeléssel és lockolással. Végül a kritikus helyeken direkt SQL taszkokkal sikerült felül kerekednünk a problémán, exkluzív tábla lokkolásokkal, meg mindenféle, de azt a néhány hetet nem kívánom senkinek. És itt csak 2(!) párhuzamos felhasználó volt, és a rendszer nem kifejezetten "misson critical", hogy Marcit idézzem. :)

A fenti, "tuti" megoldás bonyolultsága miatt most, amikor utólag merült fel a konkurencia problémája, nem szerettem volna ebbe az irányba elmozdulni, mert nem volt rá elég időm, arra viszont aztán rájöttem, hogy az általam preferált és Nektek is bemutatott félmegoldás egyáltalán nem is megoldás, mert igaz ugyan, hogy a rekordokat végül csak 1 taszk írja, de csak a rekord utó végén derül ki, hogy baj van, akkor viszont a feldolgozás (adatbeküldés felhőbe, stb.) már visszavonhatatlanul megtörtént.

Megpróbáltam az SQL Server által biztosított lehetőségek közül az application lock-ot használni, ami egy globális adatbázis mutex objektum (ezzel MySQL alatt nagyon jó tapasztalatom van), de ezt még direkt SQL taszkkal sem tudtam működésre bírni. Semmi visszacsatolást nem tudtam ugyanis kiszedni az adatbáziskezelőből, hogy sikerült-e a dolog vagy sem. (Kimeneti paramétere csak szóló SELECT utasításnak lehet, a tranzakciós változók (@result) nem őrzik meg az értéküket a direkt SQL taszkok között, lekérdező függvény nincs, ráadásul az összes helyi Magic-es taszk egy felhasználóé SQL oldalon, úgyhogy eleve nem védené meg őket egymástól...) 3-4 órám elment a kísérletezéssel.

Végül azt a megoldást választottam, hogy létrehoztam egy [TáblaNév, KontextusID] táblát, és egy programmal ebbe írom föl, ha valaki batch végrehajtást indít. Ez a taszk a már említett "Record has been changed..."-del gondoskodik róla, hogy csak 1 írhasson be, utána egy programmal kiolvastatom hogy ki van beírva, és ha a saját Kontextus ID, akkor szabad a pálya, ha meg nem, akkor bele se lép a record prefixbe. Munka végén meg kitörli magát. Vagyis tulajdonképpen implementáltam egy virtuális mutexet, és még azt is nyertem vele, hogy nem a fizikai táblát kell lockolnom, így a batch végrehajtás alatt a beírás zavartalanul mehet tovább.

Ez a megoldás most jónak tűnik, de ha szerintetek van ezzel valami gyakorlati probléma, akkor kritizáljátok meg, legyetek szívesek!

Köszi az eddigieket és az ez utániakat is!
Üdv:

Dávid

U.I.: Ámor! Én még szeretem a Magic-et, ennél a szűk határidős feladatnál - ahogy már Te is sokszor mesélted - sok fejlesztős cégeket vertem fejlesztési időben (pedig csak rész munkaidőben nyomom), de nem véletlenül imádom a PHP-t. Ott ha azt mondom, hogy BEGIN TRANSACTION, akkor az úgy is van. :) Nincs varázslat, nincs Magic. ;)

Reply all
Reply to author
Forward
0 new messages