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.