Tema: Re: Need nuomonės iš šono - DB
Autorius: 2x50
Data: 2011-12-09 00:30:49
Nevisai. Problema yra iš esmės FIFO uždavinyje, o jam realizuoti
SERIALIZABLE tinka.

Nemanau, kad serializable is viso ka nors keicia siuo atveju, bent jau ne 
gretaveikos prasme. Problema yra tame, kad visos aktyvios transakcijos bando 
uzrakinti viena ir ta pati irasa, todel ju laukimas yra visiskai 
beprasmiskas.
Pati duomenu kontrole (ACID principas) nera realizuota per transaction 
isoletion levelius, ji realizuojama per lockus t.y. nepriklausomai nuo to 
koks yra isolation levelis, transakcija susirenka tokius pacius X lockus 
(butent X lockus, kiti lockai gali skirtis), tiek serializable tiek read 
uncommited minetu atveju sukurs X locka irasui kuris bus trinamas. O kadangi 
siuo konkreciu atveju visos aktyvios transakcijos nores daryti lygiai ta 
pati (X lockas tam paciam irasui), tai jos visos tusciai lauks kol baigsis 
pirmoji, nes, kaip zinia, X ir X kombinacija yra konfliktuojanti ir tokios 
transakcijos niekada nebus vykdomos vienu metu, nepriklausomai (!) nuo 
isolation levelio.

Supaprastintai stai kas ivyks siuo konkreciu atveju, mano isivaizdavimu:

--> start transaction t1
                --> start transactio t2
--> t1 SELECT * FROM `table` ORDER BY ID ASC LIMIT 1 (tarkim grazina id=5)
                --> t2 SELECT * FROM `table` ORDER BY ID ASC LIMIT 1 
(grazins ta pati irasa id=5)
--> t1 DELETE FROM `table` WHERE `ID` = 5
--> t1 sukuria X locka irasui id=5
                --> t2 DELETE FROM `table` WHERE `ID` = 5
                --> t2 negali sukurti X locko irasui id=5, todel statoma i 
eile
--> t1 commit
                --> t2 dabar gali sukurti X locka irasui id=5

Tik beda tame, kad iraso jau nebera, todel sita transakcija viska dare 
tusciai. Klausimas tik kaip MySQL susidoroja su tokia situacija, grazina 
exceptiona ar ne.

Grieztesni isolation leveliai tiesiog sukurs papildomu locku tam, kad 
dirbtinai sukelti konfliktines situacijas, pvz. serializable atveju (siek 
tiek pakeitus scenariju, nes ankstesniu atveju viskas vyktu identiskai, kit 
su papildomais S lockais)

--> start transaction t1
--> t1 SELECT * FROM `table` ORDER BY ID ASC LIMIT 1 (tarkim grazina id=5)
--> t1 sukuria S locka irasui id=5
--> t1 DELETE FROM `table` WHERE `ID` = 5
--> t1 sukuria X locka irasui id=5
                --> start transaction t2
                --> t2 SELECT * FROM `table` ORDER BY ID ASC LIMIT 1 
(grazins ta pati irasa id=5)
                --> t2 negali sukurti S locko irasui id=5, nes t1 vis dar 
laiko X locka tam paciam irasui
--> t1 commit
                --> dabar t2 gali sukurti S locka irasui id=5

Net jei MySQL ir pasinaudos multi-verioningu ir t2 suras ta irasa, visvien 
ji negales ivykdyti delete komandos ir prasisuks tusciai, nes iraso jau 
nera.

Taigi, tarkim, kad masinos greitis leidzia viena tokia transakcija apdoroti 
per 1 sekunde ir tokiu uzklausu per sekunde sugeneruojama 3. Tai reiskia, 
kad tik kas 3cia transakcija is viso kazka padaro, bet visos turi sulaukti 
kol pasibaigs ankstesnioji. Cia kaip sukti cikla, kur tik kas 3cia iteracija 
kazka daro, tik siek tiek blogiau :)
Laike atrodytu mazdaug taip:

--> prasideda sekunde
t1 start id=5
t2 start id=5
t3 start id=5
t1 commit
--> sekunde baigiasi
t4 start id=6
t2 abort
t5 start id=6
t3 abord
t6 start id=6
t4 commit
--> antra sekunde baigesi
t7 start id=7
t5 abort
...... ir t.t.

cia dar, sakyciau, optimistinis variantas. Jei abort komandos nors kiek 
veluos, jos tiesiog kaupsis kol uzpildys viska, ka imanoma uzpildyti 
siukslemis ir greitaveikos letejimas tik dides, ir tikrai ne tiesiskai.
Geriausiu atveju greitis bus 1 irasas per sekunde, nors masina pvz. galetu 
apdoroti tokiu transakciju kelias desimtis paraleliai. Didinant generuojamu 
uzklausu intesyvuma padidetu tik papildpomas kruvis transaction manageriui 
ir lock manageriui, bandantiems kurti lockus ir abortinant tas tuscias 
transakcijas.

Skirtumas nuo dabartinio sprendimo butu tik toks, kad dabar ilgeja eile 
norinciu pradeti ir laukianciu to write lock, o su transakcijom bus daug 
siuksliu, kurias reikes sutvarkyti. Kas del serializable gali veikti tik 
leciau nei kiti isolation leveliai, nes toks grieztas veiksmas tiesiog 
naturaliai atlika daugiau veiksmu palyginus su ne tokiais grieztais 
leveliais.

Mano manymu akivaizdu, kad uzdavinio esme uztikrinti, kad kiekviena 
startuojanti transakcija apdorotu vis kita irasa. O tam neuzteks tiesiog 
migruoti i InnoDB ir parinkti transacion isoletion level. Ir dar ko dero 
reiks susitaikyti, kad 100% FIFO nesigaus, greiciau gausis first in - close 
to first out.