Jump to content
php.lv forumi

mysql dalisana - CI


goma smile

Recommended Posts

  • Replies 60
  • Created
  • Last Reply

Top Posters In This Topic

Top Posters In This Topic

Nebūtu un tas ir zināms fakts, ka ORM (vai sauc kā gribi) ir savi ierobežojumi. Arī, ir plusi.

Man nav iebildumi pret ORM, kur normāli tiek objekti mapoti pret db ierakstiem.

Man vairāk liekas nepareizi tā lieta, kas ir raksta sākumā, kad SQL sintakse tiek abstrahēta uz konkrēto valodu - respektīvi, tiek rakstits +- tas pats kverijs, bet, nevis SQL, bet konkrētajā izmantotajā backend valodā, kur sliktākajā gadījumā tas ir vienkārši metožu čeinings.

 

Piemēram, ieraugot:


for thing in Thing.objects.filter(is_foo=True)[:10]

Kā es varu zināt, ka netiks ielasiti visi objekti un tad nogriezti pirmie 10?

Tas ir ļoti mulsinoši.

No otras puses, kā es varu veikt visu ierakstu ielasi un tad nogriezt 10 - kā atšķirsies sintakses?

 

 

Tu tikai pieliki "FOR UPDATE"... domā, abstrakcijai tas būtu baigi grūti panākams?

Kā arī, neredzu, kur tu explicitly pateiktu "sākam transakciju un ieslēdzam row lock".

Ok, es vienkārsi transakcijas izmantoju defaultā un man viss actions parasti ir ievrapots transakcijā, ja tas ir pilnīg neatkarīgs piemērs, tad:

 

 

Bet row lock šijā gadijumā nodrošina tieši tas FOR UPDATE.

DB.withTransaction{
  SQL("SELECT * FROM `things` WHERE `is_foo` IS TRUE LIMIT 10 FOR UPDATE").select().as[Thing].filter(_.isBar()).map(_.update())
}

Protams, var arī šim abstrakcijas slānim kabināt klāt vienu pēc otras funkcionalitāti, bet kāda tam jēga?

Tev papildus izpratnei par SQL, jāiemācās konkrētā freimworka API versija par to kā uzģenerēt SQL.

 

 

Un vēl viena lieta - ja tev kodā mētājas apkārt vairākas references uz to pašu rowu (šajā gadījumā, vairāki objekti, kuri reprezentē to pašu rowu), tad tev ir citas problēmas, par kurām vajadzētu padomāt.

Runa ir par, piemēram,  elementāru situāciju.

Pieņemsim ir raksta lapa, kurā skaita viewus.

Kad pieprasa rakstu, tu ielāde raksta saturu, un updeito tā viewus un jauno raksta reitingu un veic ielasitā objekta updeitu:

 

Tātad:

$article=new Articel();
$article->loadById(123);
$view['text']=$article['text']
$article->calculateNewRating();
$article['views']=$article['views']+1;
$article->update();

Ja nav izmantots row locks, tad kas notiks ar viewiem.

Ja vienlaikus 2 cilvēki veiks pieprasījumu un kods izpildīsies šādi:

 

1. pieprasījums $article->loadById(123);, ielādē, ka viewi ir 10.

2. pieprasījums $article->loadById(123);, ielādē, ka viewi ir 10.

1. pieprasījums $article['views']=$article['views']+1;, palielin viewu skaitu uz 11.

1. pieprasijums $article->update(); saglabā, ka ir 11 viewi

 

2. pieprasījums $article['views']=$article['views']+1;, palielin viewu skaitu uz 11.

2. pieprasijums $article->update(); saglabā, ka ir 11 viewi

 

Rezultātā apskatijās rakstu 2 cilvēki, bet viewu skaitu palielināja par 1.

Šijā gadijumā tas ir sīkums, bet, ja nu būs aplikācija, kur runa ir par naudu?

 

Row lock gadījumā 2. pieprasijuma $article->loadById(123); gaidīs, līdz 1. pieprasījums pabeigs visas darbības ar šo rindu.

Edited by codez
Link to comment
Share on other sites

Ko tad, ja 1. pieprasījums nobremzē, vai, mazums, kaut kas notiek ne tā?

 

Macro-scale piemērs: 2 menedžeri vienlaicīgi atver kaut kādu datu rediģēšanas lapu. Abi kaut ko izmaina, bet pirmais saglabā uzreiz, otro iztraucē pa skaipu un tas saglabā pēc pāris minūtēm.

Ja pieliek row-lock, tad sanāk, ka tikai viens menedžeris drīkst kaut ko rediģēt un visiem pārējiem tiem datiem nav pieejas, kamēr šams nesaglabā datus? Vai kā tas notiek?

Labāk tad saglabāt "originalValue" un saglabājot salīdzināt ar tabulas datiem, un ja originalValue sakrīt ar tabulu, tad apdeitot uz newValue, otherwise izmest paziņojumu, ka kāds cits jau saglabājis, vajag iečekot viņu izmaiņas.

 

Row lock gadījumā 2. pieprasijuma $article->loadById(123); gaidīs, līdz 1. pieprasījums pabeigs visas darbības ar šo rindu.

t.i. garantēti visiem cilvēkiem jāgaida vienam uz otru, kamēr visiem iepriekšējiem ielādēsies lapa...

 

 

Anyway, tāpat skaidrs, ka tev labāk patīk rakstīt plikus SQL query konkrētās datubāzes dialektā un ja ievajadzēsies pāriet uz citu DB, tad visu pārrakstīt.

Tas par row lock un transakcijām vispār beztēmā aizgāja...

Edited by jurchiks
Link to comment
Share on other sites

Ko tad, ja 1. pieprasījums nobremzē, vai, mazums, kaut kas notiek ne tā?

Tad otrajā būt db timeout exceptions, kuru parasti pārtver un lietotājam paziņo, ka nav iespējams veikt darbību.

 

Macro-scale piemērs: 2 menedžeri vienlaicīgi atver kaut kādu datu rediģēšanas lapu. Abi kaut ko izmaina, bet pirmais saglabā uzreiz, otro iztraucē pa skaipu un tas saglabā pēc pāris minūtēm.

Ja pieliek row-lock, tad sanāk, ka tikai viens menedžeris drīkst kaut ko rediģēt un visiem pārējiem tiem datiem nav pieejas, kamēr šams nesaglabā datus? Vai kā tas notiek?

Labāk tad saglabāt "originalValue" un saglabājot salīdzināt ar tabulas datiem, un ja originalValue sakrīt ar tabulu, tad apdeitot uz newValue, otherwise izmest paziņojumu, ka kāds cits jau saglabājis, vajag iečekot viņu izmaiņas.

Nē, row locks darbojas vienas transakcijas, tātad viena reuqesta iervaros un tiek izmantots, lai varētu uztaisīt pareizi strādājošu aplikāciju.

Iedziļinies vēlreiz situācijā un varbūt sapratīsi, ka daļa tavu pirms tam būvēto aplikāciju, atsevišķos gadījumos var nostrādāt nepareizi.

Bet tā situāciju, kuru tu apraksti, ir pavisam no citas sērijas.

 

t.i. garantēti visiem cilvēkiem jāgaida vienam uz otru, kamēr visiem iepriekšējiem ielādēsies lapa...

Cilvēkiem ir jāgaida tikai tad, ja tiek pieprasīts viens resurs, kurš aplikācijas ietvaros tiek mainīts.

Un nevis kamēr ielādēsies viena lapa, bet kamēr beigsies transakcija viena requesta ietvaros.

 

 

Tas par row lock un transakcijām vispār beztēmā aizgāja...

Lol, tā nav beztēma, tas ir cieši saistīts ar to, ka visi šie dinamiskie sql ģenerācijas fw parasti neimplementē ļoti būtiskas sastāvdaļas.

Bet, ja tu neizmanto row lockus un transakcijas, tad finansu sistēmām tevi klāt labāk nelaist.

Link to comment
Share on other sites

> Tas ir ļoti mulsinoši.

 

Protams, ka tas būs mulsinoši. Tas tā ir tāpēc, ka nezini kā strādā Django QuerySet.

 

~~~

qs[:10] # limit 10

list(qs)[:10] # select all, slice 10

~~~

Link to comment
Share on other sites

Šorīt, ar skaidru galvu, atcerējos, ka mums arī bija problēmas ar to raw lock. Attiecīgi viena kolona tabulā tika mainīta no divām vietām (caur web un caur workeri). Labs jautājums kā risinājām — ar raw lock vai nedaudz gudrāk. :)

 

Bet šī te problēma nav common-case un šāda veida problemātiski bagi rodas ļoti reti.

Link to comment
Share on other sites

> Tas ir ļoti mulsinoši.

 

Protams, ka tas būs mulsinoši. Tas tā ir tāpēc, ka nezini kā strādā Django QuerySet.

 

~~~

qs[:10] # limit 10

list(qs)[:10] # select all, slice 10

~~~

Par to jau arī es runāju. Es zinu kā strāda python un zinu kā strāda SQL.

Līdz ar to šīs papildus abstrakcijas - QuerySet dēļ, man nav iespējams saprast uzreiz, kas precīzi notiek kodā.

Ja tā vietā būtu plain SQL kverijs, uzreiz būtu skaidrs, ko kods dara.

 

 

Bet šī te problēma nav common-case un šāda veida problemātiski bagi rodas ļoti reti.

Tā nav reta problēma, šāds stāvoklis rodas jebkurā situācijā, kurā tiek nolasīti dati, izmainīti un saglabāti un šāda darbība ar vieniem un tiem pašiem datiem var notik paralēli. Kaut vai iepriekšējais piemērs par view skaita palielināšanu rakstam.

Vienkārši ir tā, ka parasti nolasīšana, izmaiņa un saglabāšanas notiek īsā laika posmā un šī kļūda izpaužas ļoti reti un tāpēc tiek reti pamanīta. Pieļauju, ka šāda veida kļūda vienā vai otrā vietā ir lielākajā daļā dažādu web produktu.

Edited by codez
Link to comment
Share on other sites

Codez cenšas pielietot web kontekstā pamatā nevajadzīgas lietas bet daGrevis nevar saprast nafig tas vajadzīgs jo tas nav vajadzīgs. Un taisnība ir abiem.

Ja nav izmantots row locks, tad kas notiks ar viewiem.
Ja vienlaikus 2 cilvēki veiks pieprasījumu un kods izpildīsies šādi:
 
1. pieprasījums $article->loadById(123);, ielādē, ka viewi ir 10.
2. pieprasījums $article->loadById(123);, ielādē, ka viewi ir 10.
1. pieprasījums $article['views']=$article['views']+1;, palielin viewu skaitu uz 11.
1. pieprasijums $article->update(); saglabā, ka ir 11 viewi

Šis ir galīgi dumjš, pašos pamatos salauzts un mulsinošs piemērs - tā vispār nekad nedara. Konkrētajā gadījumā atjaunošana tiktu veikta vienā kverijā ar views=views+1 nevis divos kverijos un vēl lockojot rowu (what the hell)

 

Rowlockus tu izmanto ja paralēli strādā ar vieniem un tiem pašiem datiem, webā tam nav īsti daudz pielietojumu, jo webs pamatu pamatā ir sinhrons, inkrementāls crud. Codez te mēģina iejaukt smagsvara biznesa operāciju loģiku no bankošanas un techops, kura te pamatā izņemot īpašus keisus lieki maisa gaisu. Un vispār tādas aplikācijas rakstīt PHP? Tur ir jābūt nedaudz psiham.

 

Saprotiet, godātie, ka web lapelēs no kā pastāv 90% weba šāda pieeja nav vajadzīga, nekad nav bijusi un nekad nebūs. Savukārt tur, kur tā ir nepieciešama, neviens nelietos PHP, kur nu vēl šitādus ormus/ar'us. 

 

Liecieties taču mierā, for fuck sake. 

Link to comment
Share on other sites

Bet lock nekam neder. Nu padomā, viss vienkārši tiks iefrīzots (faken klients tiks iefrīzots!).

Regulārā darbībā nekas neiefrīzo.

Kolīzija, kad 2 requesti pieprasa vienus un tos pašus datus izmainīšanai ir ļoti reti (iemesls kāpēc šīs kļūdas reti kāds pamana un par tām nezin), bet

tādas ir un tajā brīdī, ja tiek izmantots row lock, otrs request pagaida pāris ms ilgāk, kamēr pirmais pabeidz transakciju.

Bet šādā gadījumā labāk ir, ka 2. requests nedaudz pagaida, nevis izpildās kļūdainas darbības. Jo, piemēram, ja runa ir par viena viewa nepieskaitīšanu, tad tas ir sīkums, bet, ja runa ir par darbibām ar naudu, vai kādām citām virtuālām vērtībām, tad tas var ne tikai radīt kādu reizi kādam lietotājam nepatikamu vai patikamu momentu, bet šāda kļūdas var tikt izmantota arī mērķtiecīgi.

Link to comment
Share on other sites

Šis ir galīgi dumjš, pašos pamatos salauzts un mulsinošs piemērs - tā vispār nekad nedara. Konkrētajā gadījumā atjaunošana tiktu veikta vienā kverijā ar views=views+1 nevis divos kverijos un vēl lockojot rowu (what the hell)

Protams +1 darbību var veikt arī ar SQL, bet tas bija tikai vienkāršs piemērs, lai varētu saprast domu.

Realitātē biznesa loģika ir daudz sarežģītāka un tā bieži vien netiek implementēta SQL.

Es personīgi nekad neimplementēju biznesa loģiku ar SQL.

 

 

Rowlockus tu izmanto ja paralēli strādā ar vieniem un tiem pašiem datiem, webā tam nav īsti daudz pielietojumu, jo webs pamatu pamatā ir sinhrons, inkrementāls crud.

Mūļķības ir simtiem elementāru piemēru, kur paralēli tiek izmantoti vieni un tie paši dati.

Piemērs:

Lietotājs sūta otram lietotājam virtuālu naudu. (piemēram, web spēlē)

Kolīzija - abi lietotāji vienlaikus nosūta viens otram naudu.

Otrajā gadijumā abi requesti izmantos vienus un tos pašus datu.

 

Vēl piemērs:

Komentāru sistēma,kura izmanto komentāriem reitinga parametru un to nerēķina ar +1-1, bet ar pietiekami komplicētu biznesa loģiku, kura nav rakstits SQLā. (piemēram, blogu platformā)

Kolīzija - 2 lietotāji paralēli balso par vienu komentāru.

 

Un tādu ikdienišķu piemēru ir daudz.

 

Codez te mēģina iejaukt smagsvara biznesa operāciju loģiku no bankošanas un techops, kura te pamatā izņemot īpašus keisus lieki maisa gaisu. Un vispār tādas aplikācijas rakstīt PHP? Tur ir jābūt nedaudz psiham.

Lieta tāda, ka banku operācijas row nelokošana nav piedodama, bet arī citās aplikācijās, kuras šeit daudzi taisa šādu kļūdu pielaišana ir regulāra.

Tās kļūdas tur ir, vienkārsi lielāka daļa par viņām nezin, jo šādu kolīziju rašānās iespēja ir tik reta, ka tas notiek varbūt pāris reizes gadā un neviens to ne tikai nepamana, bet, ja pamanītu, nemāk atkārtot un atrast cēloni.

 

Saprotiet, godātie, ka web lapelēs no kā pastāv 90% weba šāda pieeja nav vajadzīga, nekad nav bijusi un nekad nebūs. Savukārt tur, kur tā ir nepieciešama, neviens nelietos PHP, kur nu vēl šitādus ormus/ar'us.

Tātad tu saki visiem - taisiet greizas aplikācijas, nemācieties kļūt gudrāki, turpiniet pieļaut tās kļūdas, kuras vienmēr pieļaujat?
Link to comment
Share on other sites

Taisnība ir un es peikrītu, tikai saku, ka šādas darbības ir reti.

Ja izmanto ORM, tad ir diezgan liela iespējamība, ka tāda kļūta ir jebkurā aplikācijā.

Un nevis darbības ir reti, bet sakritība, kad notiek šī kolīzija, ir reti. Darbības parasti ir pietiekami bieži.

Edited by codez
Link to comment
Share on other sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

Loading...

×
×
  • Create New...