Tema: Re: Need nuomonės iš šono - DB
Autorius: Laimis
Data: 2011-12-09 19:03:03
2x50 rašė:
> is to paties linko
> Deadlocks are a classic problem in transactional databases, but they are
> not dangerous unless they are so frequent that you cannot run certain
> transactions at all.
> Noriu atkreipti demesi i ta sakinio dali nuo zodziu "unless they".

Norima pasakyti, kad ribinėje situacijoje, kai deadlock'ai vyksta taip 
dažnai, kad beveik beveik garantuotai, tai tiesiog tampa problematiška 
vykdyti kai _kurias_ (turimas omenyje specifiškumas, o ne bendrumas) 
transakcijas, nes jos tiesiog neįvyksta dėl to, kad negali konkuruoti 
eilėje su aibe kitų. Na, pavyzdžiui, jei krūva tokių pačių konkurentiškų 
transakcijų valgo FIFO eilę ir aibės jų nuolat 
konfliktuoja/deadlock'inasi, tai taptų problematiška įvykdyti kokias 
nors *specifines* transakcijas, kurios, pavyzdžiui, priklauso nuo kelių 
užlock'intų įrašų ar range-lock'ų.
Konkrečiu atveju ši problema nėra (tokia) aktuali, nes bent viena iš 
tokios pačios padermės transakcijų bet kokiu atveju įvyksta.


> Manau, kad
>
> begin transaction
> set transaction isolatio level serializable
> select * from tbl where id = 5
> delete from tbl where id = 5
> end transaction
>
> ir bus butent tas "unless they" atvejis. Kodel? Todel, kad (anot
> dokumentacijos) su set transaction isolatio level serializable select
> dalis kuria S locka, ne X. Isvada tokia

Ne, tai nebus tas atvejis. Net ir ribiniu atveju, kai kas sykį 
užsideadlock'ina koks dešimtis ar net šimtas transakcijų. Žr. aukščiau. 
Ir žemiau :-)

>
> begin transaction
> set transaction isolatio level serializable
> select * from tbl where id = 5
> delete from tbl where id = 5
> end transaction
>
> nera tas pats kaip
>
> begin transaction
> set transaction isolatio level serializable
> select * from tbl where id = 5 FOR UPDATE
> delete from tbl where id = 5
> end transaction

Nėra tas pats, tačiau ribiniu atveju abu būdai greitaveikos prasme panašūs.
Pirmuoju atveju, kitos besipešančios transakcijos sąlygos deadlock'ą, 
kuris įvyks po pirmosios (vienos transakcijos) darbo pabaigos ir 
commit'o, o antruoju — besipešančios transakcijos sustos į eilutę ir 
lauks, kol bus įvykdyta pirmoji ir tik tada, paeiliui po vieną, tęs savo 
darbą.
Tai jei sąlygos tokios, kad sykiu įvyksta, tarkime, 100 tokių 
besipešančių transakcijų, o viena transakcija įvykdoma per 1 ms, tai 
nėra jokio skirtumo ar:
pirmuoju atveju, kas 1 ms bus bus įvykdoma po transakciją, o 99 jų 
atmetamos ir gali bandyti iš naujo.
antruoju atveju visas šimtas sustoja į eilutę ir kas 1 ms sau vykdomos
paeiliui.



>
> ir pirmasis atvejis nera pakankamas tam, kad sustatyti transakcijas i
> eile. Kai kurios visvien prasides dar tada, kai anstesne dar nera
> pasibaigusi, bet ir dar neturi X locko (ivykde select bed dar nepradejo
> delete). Va cia yra potencialus kandidatai deadlockams. Kurie, savo
> ruoztu, nedaro nieko naudingo, o tik tusciai naudoja masinos resursus.

Na ir kas? O antruoju atveju visos jos stos į eilę tik todėl, kad viena 
iš jų, t.y. „anstesne dar nera pasibaigusi (ivykde select bed dar 
nepradejo delete“

Deadlock'as yra natūrali situacija, kai tampa aišku, jog transakcijos 
negali būti įvykdytos lygiagrečiai, palaikant nuoseklumo iliuziją. 
Resursų, rakinant ir sekant eiliškumą reikia abiem atvejais ir turbūt 
reikia bemaž vienodai.
>
> Nebent dokumentacijoj parasyta ne visai taip kaip veikia. Jei MySQL
> atveju FOR UPDATE ir SERIALIZABLE veikia vienodai, tada nebutu jokio
> skirtumo kaip naudoti - transakcijos stotu i eile pries prasidedamos
> (tiksliau, pries pradedamos vykdyti pirmaji select sakini).

Veikia skirtingai. Jei lygiagrečios transakcijos nesipeša, tai 
SERIALIZABLE izoliacijos atveju jos gali vykti lygiagrečiai, kai tuo 
tarpu FOR UPDATE bet kokiu atveju blokuojamas skaitymas (neįmanomas 
lygiagretus vyksmas).

> Is kitos puses, naudojant FOR UPDATE, visiskai nera reikalo naudoti
> serialiniu transakciju (tokiam kontekste koks cia parasytas), nes FOR
> UPDATE yra dar grieztesnis mechanizmas, nei serialine transakcija.
> is to paties linko
> If you are using locking reads (SELECT ... FOR UPDATE or SELECT ... LOCK
> IN SHARE MODE), try using a lower isolation level such as READ COMMITTED.

Try nelygu „Should“ ar „Better use“.

> Siaip bendra taisykle yra tokia - naudok serialines transakcijas tik
> tais atvejais, kai tai yra butina, jei tai nera butina, nenaudok, jos
> nieko gero neduoda. Todel ir siulau ju nenaudoti, ypac jei yra select
> ... for update. Kam tas galvos skausmas su deadlockais ir transakciju

Nesu girdėjęs tokios taisyklės. Esu girdėjęs, kad reikia taip 
projektuoti, kad duomenys būtų teisingi (consistency, integrity), o tam
parenkamas tinkamas izoliacijos lygis, kuris užtikrina duomenų 
teisingumą (išvengia problemų). Izoliacijos lygį, kai sąveika/logika 
nėra visiškai aiški, siekiant išvengti visų duomenų teisingumo problemų, 
kurios gali kilti transakcijų sraute, kaip tik ir derėtų parinkinėti nuo 
kito galo, t.y. nuo SERIALIZABLE.

Beje, kaip jau minėjau, MySQL atveju REPEATABLE READS (default) ir 
SERIALIZABLE yra mažai kuo skirtingos.

> Nesigincysiu su tuo, kad InnoDB veiks greiciau nei MyISAM, nes nezinau,
> bet kaip rasiau ansciau, mano manymu, tai yra lavono gaivinimas.
> Padidinus konkurentiniu sesiju skaiciu, problema vel islys. O tada jau
> nebebus kur migruoti is InnoDB. Tai nera problemos sprendimas, tai yra
> sprendimo atideliojimas. Nors, kas zino galbut to ir visam sistemos
> gyvenimui uzteks :)

Na ir kokį gi kitokį sprendimo būdą matai FIFO uždaviniui...?

>
> Is to paties linko
> If nothing else helps, serialize your transactions with table-level locks.

Tai pasiūlymas, kai jau niekas negelbėja ir jau kai pats nebesusigaudai, 
kas tavo duomenų bazėje ir programose vyksta...


>
> Ka noriu akcentuoti
> SELECT * FROM `table` ORDER BY ID ASC LIMIT 1 FOR UPDATE
> yra lygiai tas pats, kas lockinti visa lenta, todel kad pati selecto
> konstrukcija yra tokia, kad vienu metu visos aktyvios transakcijos, kiek
> ju bebutu, bandys rakinti viena ir ta pati irasa. Su tokiu selectu nera
> imanomas variantas, kad 2 transakcijos paraleliai bandytu rakinti
> skirtingus irasus. Na, su FOR UPDATE problemu nebus zinoma, bet be FOR
> UPDATE ir su serialinem pasipils deadlockai. Be FOR UPDATE ir su bet

Nepasipils dėl banalios priežasties, kurią pats ir įvardinai: visos 
konflikuojančios transkacijos vyksta *nuosekliai* (po vieną).


> ne visai FIFO, kazkoks "beveik FIFO", bet leidzia suktis
> nekonfliktuojancioms transakcijoms paraleliai apdorojant skirtingus
> irasus tuo paciu metu. Ar is tiesu yra labai didelis skirtumas tame, kad

Ir vėl gi. Jeigu skaitytum atidžiau... ;-)
Būtent toks būdas ir buvo pasiūlytas, kai transakcijos konfliktuoja tik 
besidalindamos id (kas yra gana spartus procesas), o toliau jau 
kiekviena jų atskirai ir lygiagrečiai atlieka savo darbą.