Multiuser webalkalmazás és az egyidejű adatbázis műveltetés.
Sziasztok!
A címben már említett témát szeretném kivesézni, azaz többfelhasználós rendszerek adatbázis kezelése azonos időben. Foglalkoztam már többször ezzel a témával, és valójában már van egy eljárás, ami alapján figyel az adatbázis műveltető rutinom a módosításra kerülő rekord állapotára, de mégis, ki hogyan élte meg az ilyen és ehhez hasonló helyzeteket?
Csak azért hogy nyílt lapokkal játsszak elmondom én hogyan csináltam meg.
Ja! és nem ér hangosan nevetni! ;)
Egy teljesen egyszerű termék és darabszám adatbázisról van szó, amit az üzletkötők mobil internettel elérnek, így a nap bármelyik pillanatában friss raktári információval rendelkeznek.
Alapvetően az adatbázis műveletek tekintetében kizárólag a készlet csökkentés, és a készlet növelésnek van jelentősége, mert ugye:
Azonos időben módosításra meghívott rekordok közül az lesz a végleges, amelyiket majd időben később mentik.
Az első megoldásom nem volt túlságosan hosszú életű:
Adtam minden rekordnak egy állapotjelzőt, amelynek az értéke ha 0 akkor módosítható, ha 1 akkor éppen meg van nyitva módosításra. Amikor a kiválasztottam a rekordot, állapotjelző egyre vált, amikor a módosítás lezajlik (OK) vagy direkt módon meg van szakítva (Mégsem) akkor visszavált 0-ra. Ez baró volt, addig, amíg egy elegáns mozdulattal be nem zárták a folyamatot végrehajtó ablakot. Meg aztán volt olyan is, hogy éppen nyitva maradt az ablakocska néhány órára, és ugye akkor mindenki más vár az információra.
Az ablak bezárást, kezeltem egy AJAX kéréssel, ami az onUnload eseményre fut le, de voltak problémák az ignore_user_abort ellenére is. Sokszor maradt a rekord foglalt.
Ekkor kitaláltam a második megoldást:
Nem 0 és 1 állapotjelzőt használtam a rekord foglaltságának jelöléséhez, hanem időbélyeget, amit összehangoltam a végrehajtó ablakban egy timeout rutinnal. Pl.: a rekord kiolvasásakor az állapotjelzőt a (most+5perc) időbélyegre állítom, és az ablaknak adok egy 5perces timeoutot.
Így az eredeti példány (aki először olvassa azt a rekordot) számára van 5perc hogy dolgozzon a rekorddal. Ha lejár, az oldal újratölt, kiüti az időbélyeget 0-ra és kijelentkezik a kezelő felületről. Ezzel kivédtem az ottfelejtést, és az ablak bezárást is, mert legfeljebb 5 percre maradnak elérhetetlenek az adatok. Hihetetlen hogy az idő múlása micsoda előnyöket tud rejtegetni!
Ez már egy életképes eljárássá forrta ki magát. Jelzi a felhasználóknak a rekord foglaltságát, biztosít lehetőséget a rekord csak olvasható módban történő megnyitására és nem utolsó sorban felhasználó függetlenné tettem az adatok újra rendelkezésre állását.
Nagyjából ennyi lenne az én tapasztalatom a témában, és jól bírom a kritikát ha az építő!
s_volenszki
■ A címben már említett témát szeretném kivesézni, azaz többfelhasználós rendszerek adatbázis kezelése azonos időben. Foglalkoztam már többször ezzel a témával, és valójában már van egy eljárás, ami alapján figyel az adatbázis műveltető rutinom a módosításra kerülő rekord állapotára, de mégis, ki hogyan élte meg az ilyen és ehhez hasonló helyzeteket?
Csak azért hogy nyílt lapokkal játsszak elmondom én hogyan csináltam meg.
Ja! és nem ér hangosan nevetni! ;)
Egy teljesen egyszerű termék és darabszám adatbázisról van szó, amit az üzletkötők mobil internettel elérnek, így a nap bármelyik pillanatában friss raktári információval rendelkeznek.
Alapvetően az adatbázis műveletek tekintetében kizárólag a készlet csökkentés, és a készlet növelésnek van jelentősége, mert ugye:
Azonos időben módosításra meghívott rekordok közül az lesz a végleges, amelyiket majd időben később mentik.
Az első megoldásom nem volt túlságosan hosszú életű:
Adtam minden rekordnak egy állapotjelzőt, amelynek az értéke ha 0 akkor módosítható, ha 1 akkor éppen meg van nyitva módosításra. Amikor a kiválasztottam a rekordot, állapotjelző egyre vált, amikor a módosítás lezajlik (OK) vagy direkt módon meg van szakítva (Mégsem) akkor visszavált 0-ra. Ez baró volt, addig, amíg egy elegáns mozdulattal be nem zárták a folyamatot végrehajtó ablakot. Meg aztán volt olyan is, hogy éppen nyitva maradt az ablakocska néhány órára, és ugye akkor mindenki más vár az információra.
Az ablak bezárást, kezeltem egy AJAX kéréssel, ami az onUnload eseményre fut le, de voltak problémák az ignore_user_abort ellenére is. Sokszor maradt a rekord foglalt.
Ekkor kitaláltam a második megoldást:
Nem 0 és 1 állapotjelzőt használtam a rekord foglaltságának jelöléséhez, hanem időbélyeget, amit összehangoltam a végrehajtó ablakban egy timeout rutinnal. Pl.: a rekord kiolvasásakor az állapotjelzőt a (most+5perc) időbélyegre állítom, és az ablaknak adok egy 5perces timeoutot.
Így az eredeti példány (aki először olvassa azt a rekordot) számára van 5perc hogy dolgozzon a rekorddal. Ha lejár, az oldal újratölt, kiüti az időbélyeget 0-ra és kijelentkezik a kezelő felületről. Ezzel kivédtem az ottfelejtést, és az ablak bezárást is, mert legfeljebb 5 percre maradnak elérhetetlenek az adatok. Hihetetlen hogy az idő múlása micsoda előnyöket tud rejtegetni!
Ez már egy életképes eljárássá forrta ki magát. Jelzi a felhasználóknak a rekord foglaltságát, biztosít lehetőséget a rekord csak olvasható módban történő megnyitására és nem utolsó sorban felhasználó függetlenné tettem az adatok újra rendelkezésre állását.
Nagyjából ennyi lenne az én tapasztalatom a témában, és jól bírom a kritikát ha az építő!
s_volenszki
tranzakciók?
milyen adatbáziskezelő (gondolom MySQL). 5-ben egészen jól működnek már a tranzakciók! Ez a módszer, amit írsz számomra picit idegenül hangzik. Szerintem a tranzakciók helyes használata megoldja ezeket a gondokat, csak jól kell kezelni őket. Nekem picit fura amit írsz, de persze működhet, csak lehet, hogy ezt rá kellene bízni a DB-re, és nem az alkalmazásban hegeszteni :)
Igen, egyetértek!
Köszönöm a véleményt, üdv:
s_volenszki
szerk: Ja és szívesen olvasnék néhány gondolatot azzal kapcsolatban, hogy az adattáblák, rekordok olvashatósága, írhatósága hogyan változik, illetve hogyan változtatható tranzakió alatt!
Erre én is kíváncsi lennék, hogyan lenne lényegesen egyszer
Amennyit én sejtek hozzá:
A tranzakció arra való hogy bizonyos feltételek mellett változzanak meg az adatok, vagyis pl ha bizonyos adatok megváltoztak közben, akkor kivételkezeléssel érvénytelen lesz a művelet. De ez nem oldja meg azt a problémát, hogy csak x ideig dolgozhasson egy adatrészlettel egy user, ezt külön kell lekezelni, kb úgy, ahogy s_volenszki írta. Ha tranzakciót használna, minimális mértékben biztonságosabb lenne, de kb ugyanilyen elven kellene megoldani.
Vagy tévedek?
Heartbeat?
Ha a böngészőt bezárják vagy elnavigálnak az oldalról, netán megszakad a kapcsolat, akkor nem fut le az AJAXos "szívdobbanás", és az időbélyeg elavul mondjuk 3 perc alatt.
Ezzel a technikával nem szorítanád 5 percre a munkát, hiszen előfordulhat, hogy a jóembernek pár percre ott kell hagynia egy félig kitöltött űrlapot.
Tranzakciók helyett atomikus műveletek
Ezzel szemben viszonylag egszerű módszer, ha az egyes változásokat kapod meg a klienstől. pl: Lenne egy eladtam és egy felvettem funkció. Ha elad, megnyomja a kis plusz gombot, és oda beírja, mennyit. A szerver pedig ennyivel növeli vagy csökkenti a készletet.
A problémát nem az egyidejű adat műveltetés jelenti, hanem.
Minta folyamat:
1. Adott termék készlet értéke ami (5db) letöltődik user_1-hez kliens oldalra.
2. Ugyanazon termék készlet értéke (5db) letöltődik user_2-höz kliens oldalra, anélkül hogy figyelmeztetnénk, valaki pillanatnyilag használja a terméket.
3. user_2 gyorsabb mint user_1 és kiadja mind az 5db-ot,
4. majd user_1 0 alá csökkenti a készletet, hiszen ő azt látta hogy a készlet 5db, és mire kiadja már nem is?
Az AJAX-os heartbeat jó megoldásnak hangzik, az időkorlát miatt eltöltődő oldal adatainak meg lehet csinálni egy un. munkamenet helyreállító rutint, ahol user a következő bejelentkezésnél visszakaphatja a formját az aktuális szerver oldali és az álltala félig bevitt kliens oldali adatokkal.
Kezd tetszeni a téma, kérlek szépen titeket, agyaljunk még!
s_volenszki
fordított logika
eleve nem lenne szabad megengedni, hogy nulla alá csökkentse, hanem vissza kéne adni a hibát, hogy már nincs 5 darab raktáron (vagy esetleg lefoglalni a maradékot, és visszaírni, hogy ennyit sikerült, bocsi).
szerintem elegánsabb dolog lenne, ha ajax-szal bizonyos időnként frissítenéd a kliens oldalon lévő darabszámot, mert a korlátozás teljesen felesleges lehet pl olyan esetekben ahol valaki csak meg akarja nézni a készletet és nem fog egyetlen darabot sem rendelni, mégis 10 percig blokkolja a forgalmat.
Tudtam!
Már amikor leírtam akkor tudtam, hogy a következő hozzászóló :) azt fogaj mondani, miért engedem 0 alá csökkeni a készletet.
Akkor most lefordítanám magyarra:
Ha az üzletkötő véres verejtékkel beküzdi magát bizalmi pozícióba és az értékesítés már csak a rendelkezésre álló készlet függvényében lesz sikeres, akkor nem megengedhető hogy amíg Ő kiajánlja a készletet, más kiadja alóla!
Még általánosabban: Ígéret szép szó...
s_volenszki
szerk:
Mellesleg a gondolattal egyetértek a felesleges foglaltsággal kapcsolatban, de mivel webalkalmazásról beszélünk, itt sokkal könnyebben irányítható a felhasználó, és a készélet elemzés read only módban rendelkezésre állhat!
szerk2:
Sajnos nem írtam le teljesen egyértelműen, de az oldal időkorláta nem kizárólag a betöltődéstől számol. Minden az oldalon bekövetkező egér, billenytű esemény lenullázza. Tehát a tényleges lejárat kiozárólag akkor következik be ha nem dolgoznak a form-mal!
Ki lockol már megint?
Ez így is van.
s_volenszki
Simán mehet nulla alá.
ID ARU MENY
1 1 +3
2 1 -1
3 1 -2
4 1 -1
Namost ha az én ID-m 3, akkor összeadom a mozgást az én ID-mig (<=), ha nullánál nagyobb szám jön ki, akkor minden renben. Ha nem, akkor törlöm és és értesítem a megfelelő ID-jű felhasználót, hogy a lezárásra már nem tudtam mindent lefoglalni, nézze át a csökkentett listát és döntse el, hogy kell-e. Az ID-k helyett gondolom megy időbélyeggel is.
Az előnye az, hogy miután az életben sem az a jellemző, hogy az utolsó darabokért a neten harcolnak, ez relatív kevés erőforrással megoldható. Persze itt is használható a ésszerű minimum készletes figyelmeztetés.
Lock
Lehet fejleszteni, hogy nem az egész készletet lockolja. Ha tudjuk, hogy "senki sem vett még 3nél többet ebből", akkor mondjuk 6 elem befoglalása egy ésszerű korlát lehet, és a többiek addig a maradék készlet erejéig dolgozhatnak.
igen, a szándék kell hogy irányítson
Találtam valamit! Akit érdekel és jó angolból, nagyon sok tanulságot fog levonni belőle! Kizárólag elméleti az anyag (már ehhez a topichoz képest)!
Handling data concurrency violation
s_volenszki
kis kiegészítés
Szerk.: én konkrétan ezt úgy csinálom, hogy addig fut egy while ciklus a "fontos művelet" elkezdése előtt, amíg nem tudja visszaolvasni a saját lockját, vagy el nem telik az előzőleg kiadott lock lejárati ideje. Ha ez utóbbi van, vagy nincs is lock kiadva, akkor megpróbálja a saját lockját elhelyezni, ami után újból indul ez a while ciklus a korábbi feltétellel.
Nagyon sok LOCK
Bocs, ha nehezen érthető, egy kis példa:
Re: Nagyon sok LOCK
felesleges LOCK
Üdv,
Felhő
működően életszerűtlen - gondolatok a kereskedelemről
üzletkötők egymás elől "lopják el" az árut, ahelyett, hogy valaki összefogná őket (mondjuk kereskedelmi vezető?)
és a kiszállítás ideje? mi van, ha valakinek jövő péntekre kell az áru, valakinek jövő hétfőre, és közben jövő szerdán megérkezik egy beszerzés? mondjuk a jövő pénteki szállítási igény fut be előbb, és az kiüti a tulajdonképpen teljesíthető hétfői igényt?
egy jól működő kereskedelem "tudja", hogy egy termékből - ha nem is két hónap múlva, de - a jövő héten mennyi fog elmenni. kalkulál minimumkészlettel, beszerzési és szállítási határidőkkel.
szóval csak azt akarom mondani, az igazán sikeres cégek nem így csinálják. a rendszer megreformálása meg nem a programozó dolga...
Adatzárolási startégia.
Átolvastam azokat a dokumentumokat amiket találtam és amiket ajánlottatok (külön köszönöm Felhőnek!), és igazából tökéletesen helyére került ez a kérdéskör.
Mint minden rendszer tervezésnél, itt is az elsődleges feladat meghatározni a rendszer célját, majd ezek után kell felépíteni a cél eléréséhez legmegfelelőbb működést. Teljesen egyetértek sotetbarna hozzászólásával, és mivel most már tudom, hogy milyen logikai eljárások vannak adatkonkurencia kezelésre, azt is tudom, hogy ebben a helyzetben nem a pesszimista modelt kell választanom.
Köszönöm a gondolatokat, üdv:
s_volenszki
concurrency control
Például: http://www.agiledata.org/essays/concurrencyControl.html
Üdv,
Felhő