ugrás a tartalomhoz

Session rekord lockolás MySQL-ben (innoDB)

tisch.david · 2010. Jún. 10. (Cs), 23.19
Sziasztok!

Régi motoros vagyok az SQL területén, most mégis a segítségeteket kérném $subject témában.
Bizonyos kiegészítő session információkat a session rekordba szerializálva tárolok. Hogy valaki párhuzamos hívásokkal ne üthesse agyon ezeket, a kérés kiszolgálásának elején SHARED LOCK-ot teszek a rekordra. Ha viszont egy admin indít egy termék betöltést, az akár 30 percig is futhat. Ha közben egy másik böngésző ablakban is kattint, akkor mi történik? Frissítenem kéne az "utolsó használat ideje" mezőt a rekordban, amihez exkluzív lock kéne. Ekkor vár 30 percig? Vagy dead lock lesz, amikor a másik is a végén vissza akar írni a rekordba?
A dolog azért érdekes csak, mert a session kezelés háza táján a logban rendszeresen felbukkannak dead lock hibák, és ennek szeretnék a végére járni.

Előre is köszönöm a válaszokat!
Üdv:

Dávid
 
1

Ha jól értelek, akkor a

Ifju · 2010. Jún. 11. (P), 14.21
Ha jól értelek, akkor a következő eset történik:

Lockolsz egy rekordot, amivel lehetővé teszed, hogy másik tranzakció olvassa a rekordot, de nem írhatja.

Kattintás másik ablakban:
Egy másik tranzakcióban újra csinálsz egy shared lock-ot, és ezt a tranzakciót várhatóan hamarabb zárod, mint az elsőt, így a második tranzakciód várakozik az első lock feloldására, hogy végre tudja hajtani az írást. Eltelik az innodb lock wait timeout-ban meghatározott idő (50 sec szokik lenni), és a második tranzakció elhasal, mivel az első tranzakció még nem zárult le.

Ebből nem lesz a szó szoros értelemben vett deadlock szvsz. Azt érdemes figyelembe venned, hogy az innodb_lock_wait_timeout határozza meg, hogy meddig vár egy tranzakció egy lock feloldására.
2

Valahogy úgy...

tisch.david · 2010. Jún. 11. (P), 15.44
Szia!

Köszi a választ! Szerintem is valami ilyesmi történik, ami 2 kérdést vet fel:
1. Mitől lesz mégis dead lock a logban. :) (Úgy néz ki, hogy ezek szerint nem ettől, úgyhogy még gondolkozom.)
2. A session-ös példában fölvetett helyzetre milyen jó megoldás létezik?
Szerintem szebb lenne, ha exklizív lock-al fognám meg a session rekordot, de így sem, úgy sem tud addig kattintani, amíg a másik kérés le nem fut. Tud valaki erre jó megoldást?

Üdv:

Dávid
3

Exclusive lock esetén azt

Ifju · 2010. Jún. 11. (P), 15.57
Exclusive lock esetén azt éred el, hogy egyszerre csak egy szálon tudod használni a sessiont, ami egy fél órás feldolgozás esetén okozhat usability problémát, pl: kapcsolat timeout 300 másodperc után.

Én csak akkor lockolnám a session rekordját, amikor feltétlenül szükséges: a visszaíráskor. A visszaírást pedig kezdeném azzal, hogy felolvasom újra a session rekordot egy másik változóba, és csak a változásokat írnám vissza. Ehhez lehet át kell alakítanod a session-kezelésedet kicsit.
4

Igen, az exkluzív lock ezt

tisch.david · 2010. Jún. 11. (P), 22.49
Igen, az exkluzív lock ezt hozza magával, de jelenleg shared lock-al is csak 1 szálas a session. :(
Az általad javasolt megoldás nekem is eszembe jutott már, azért vetettem el mégis, mert jelenleg úgy működik a session kezelés, hogy az engedélyezett inaktivitási időnél régebbi inaktív session-ök kapnak egy inaktív flag-et, majd néhány perce múlva törlődnek. Ezért kell most végig fognom azt, amelyik dolgozik. Van jobb ötleted a session-ök kitakarítására? Hagyjak esetleg nekik több időd, mondjuk a lejárat után 1 nappal töröljem őket, feltéve, hogy nincs olyan hosszú batch processz?

Előre is köszi a tippeket!
Üdv:

Dávid
5

Batch

Ifju · 2010. Jún. 12. (Szo), 11.16
Én külön választanám a batch folyamatot a sessiontől. A batch folyamat eredményét később is el lehet juttatni a felhasználóhoz, amikor már végzett, addig meg minden oldalletöltésnél ki lehet írni neki, hogy folyamatban van.

A batch folyamat indításakor zárod a sessiont, kiírod a felhasználónak, hogy a folyamat elindult, esetleg egy percenként frissülő oldalon kiírhatod neki, hogy mit csinál a folyamat éppen, csak meg kell oldani, hogy a folyamat valahova beírja ezt, ahonnan fel tudod olvasni a felhasználónak.

A session-t nem érdemes olyan munkafolyamatokba belevinni, amelyeknek potenciálisan később lesz vége, mint ahogy lejárna a session.

Viszont másik megoldás lehet az is, hogy amikor a batch folyamat elindul, akkor raksz a session-re egy flaget, ami kitolja a lejárati idejét, és jelzés a garbage collectornak, hogy ne takarítsa ki a sessiont, mert fut egy folyamat vele kapcsolatban. Talán ez egyszerűbb megoldás, mint az előző, és így nincs szükség arra, hogy fél órára lockolj egy rekordot, amit amúgy írnál-olvasnál.
6

Köszönöm a választ!

tisch.david · 2010. Jún. 14. (H), 09.04
Köszönöm a választ! Gyakorlatilag ez tűnik az egyetlen jó megoldásnak. Nekem személy szerint most a második javaslatod áll jobban kézre.
Egy elméleti kérdésem lenne még:
A vannak bizonyos adatok, melyet a session-be szerializálva tárolok. Ugyan az említett hosszú batch folyamat nem módosítja ezek egyikét sem, de elvileg akár módosíthatná is. Ebben az esetben nem járható az általad javasolt út, mert ha a folyamat végén (módosítás előtt) újra felolvasom a session adatokat, akkor inkonzisztens állapotba kerülhet a futó szál. Erre van valami ötleted?

Köszi!
7

Írd át a session handlered

Ifju · 2010. Jún. 14. (H), 09.33
Írd át a session handlered úgy, hogy figyelje, mikor mi változik benne, és mielőtt perzisztálja a sessiont egy tranzakcióban visszaolvasod a session rekordot a DB-ből, a változásokat átvezeted, és így írod vissza a DB-be, tranzakció vége.

Ezzel megoldod, hogy csak a változások kerülnek a DB-be.

Ezt tovább lehet bonyolítani/finomítani, hogy minden session adathoz még rendelsz egy timestampet is a session handleren belül, és csak azokat az adatokat frissíted, amelyeknek a timestampje régebbi, mint a változásod.
8

Bocs, azt hiszem

tisch.david · 2010. Jún. 15. (K), 10.14
Bocs, azt hiszem félreértettél. Az világos számomra, hogy - összhangban korábbi ötleteddel - egy "2 menetes" session kezelést technikailag hogyan kéne megvalósítani. Az elvi probléma, amit feszegetni szerettem volna az, hogy a sessionben lehetnek olyan adatok, melyeket kizárólagosan kéne használni. Olyan struktúrák (tömbök) pl., melyekkel a session dolgozik, és alakítja őket, majd kiírja a végén. Amiket ezért - egy 2 menetes session kezelés esetén - az első, hosszabb futású session végén merge-ölni kéne (ha lehet) a második, rövidebb futású session által előállított struktúrával, nem csak egyszerűen eldönteni, hogy melyik a frissebb, és akkor az él.
Mivel ez a probléma - szerintem - teljes általánosságban nem orvosolható máshogy, csak az erőforrás kizárólagos használatának biztosításával, ezért vetettem el az elején a 2 mentes session kezelést.
Arra lennék kíváncsi, hogy Neked van-e valamilyen ötleted ennek a - valószínűleg pusztán elméleti - problémának a megoldására?

Köszi! Üdv:

Dávid
9

Meglehetősen összetetté válik

Ifju · 2010. Jún. 16. (Sze), 09.04
Meglehetősen összetetté válik így már a probléma, viszonylag egyszerű ás általános megoldást szerintem erre nem is lehet így adni, viszont a lockolással a párhuzamos munkát ki is zártad.

Ilyen esetben a shared lock sem megfelelő megoldás, mert a második session a lock feloldása után (lock wait timeout nélkül) a saját adataival felülírná az adatokat, és nem merge-lné.

Általános megoldásra nekem sincs javaslatom.
10

Köszönöm a rám szánt időt!

tisch.david · 2010. Jún. 16. (Sze), 09.32
Örülök, hogy megerősítettél. Mivel a párhuzamos használat mindenképpen cél, valami kompromisszumos megoldást fogok keresni. Hasznos volt számomra ez a kis eszmecsere.
További szép napot!

Dávid