PHP, MySQL ochrana paralelne spustenych skriptov
PHP, MySQL ochrana paralelne spustenych skriptov
Ahojte, mam dost jednoduchu otazku:
Ak v PHP nacitam z DB hodnotu, pracujem s nou (upload obrazku) a nasledne ju ulozim spat do DB navysenu o 1, aka je sanca, ze rovnaky skript spusteny paralelne inou osobou dostane rovnaku hodnotu?
Priklad:
1) nacitam z DB hodnotu ID = 123
2) uploadnem obrazok, ktory sa ulozi na disku ako 123.jpg
3) do databazy ukladam ID = 124 (aby nasledujuci obrazok bol 124.jpg...)
sucasne ak sa spusti dalsi skript (prvy sa este nedokoncil), tak opat mi to nacita ID = 123?
Alebo je na toto PHP / MySQL alebo Apache pripraveny a problem nenastane?
Dakujem
Ak v PHP nacitam z DB hodnotu, pracujem s nou (upload obrazku) a nasledne ju ulozim spat do DB navysenu o 1, aka je sanca, ze rovnaky skript spusteny paralelne inou osobou dostane rovnaku hodnotu?
Priklad:
1) nacitam z DB hodnotu ID = 123
2) uploadnem obrazok, ktory sa ulozi na disku ako 123.jpg
3) do databazy ukladam ID = 124 (aby nasledujuci obrazok bol 124.jpg...)
sucasne ak sa spusti dalsi skript (prvy sa este nedokoncil), tak opat mi to nacita ID = 123?
Alebo je na toto PHP / MySQL alebo Apache pripraveny a problem nenastane?
Dakujem
-
harrison314
Hardcore addict
- Príspevky: 8217
- Registrovaný: 27 máj 2009, 20:42
- Bydlisko: Bratislava
- Kontaktovať používateľa:
Re: PHP, MySQL ochrana paralelne spustenych skriptov
Nezanedbatelna.Boccaccio napísal:Ak v PHP nacitam z DB hodnotu, pracujem s nou (upload obrazku) a nasledne ju ulozim spat do DB navysenu o 1, aka je sanca, ze rovnaky skript spusteny paralelne inou osobou dostane rovnaku hodnotu?
Bud pouzijes trasnakcie alebo zmenis navrh.
//autoeditácia príspevku (26 Jún 2015, 12:42)
Alebo Id budes mat ako autinkremenet, ulozis zaznam do databazy a potom ulozis subor na disk, ak sa to nepodari zaznam zmazes. Alebo budes generovat nazvy inak napriklad pomocou GUID-ov.
-
Michaelo
Hardcore addict
- Príspevky: 6177
- Registrovaný: 16 júl 2008, 20:29
- Bydlisko: Pri PC
- Kontaktovať používateľa:
Re: PHP, MySQL ochrana paralelne spustenych skriptov
Na toto som sa pytal na StackExchange minule, kedze mi to vrtalo v hlave: http://programmers.stackexchange.com/qu ... -be-missed
Re: PHP, MySQL ochrana paralelne spustenych skriptov
Cize harrison sa myli vo svojej odpovedi?Michaelo napísal:Na toto som sa pytal na StackExchange minule, kedze mi to vrtalo v hlave: http://programmers.stackexchange.com/qu ... -be-missed
-
audiotrack
VIP
- Príspevky: 25958
- Registrovaný: 09 sep 2005, 18:39
- Kontaktovať používateľa:
Re: PHP, MySQL ochrana paralelne spustenych skriptov
áno, mýli. ALe tá odpoveď z toho stacku je tiež trošku zjednodušená a zidelaizovaná. Záleží aké tabuľky a isolation level používaš. Pre layer 3 si musíš definovať zámok pomocou select for update, pre layer 4 sa automaticky tento zámok vytvára ak je select nasledovaný updatom. V praxi ale takéto veci neriešiš, lebo ak máš vela konkurentných requestov na db, skôr budeš musieť riešiť segmentáciu a plno iných problémov aby ti to tá db vôbec stíhala a tým vyriešiš aj toto
-
harrison314
Hardcore addict
- Príspevky: 8217
- Registrovaný: 27 máj 2009, 20:42
- Bydlisko: Bratislava
- Kontaktovať používateľa:
Re: PHP, MySQL ochrana paralelne spustenych skriptov
Nehovorim, ze moje rienie je nepristrelne. Ale riesnie od Boccaccia by som nikdy nepouzil, a viac informacii k tomu nedal.audiotrack napísal:áno, mýli.
Re: PHP, MySQL ochrana paralelne spustenych skriptov
audiotrack, harrison314 - poradte mi prosim 
Stale sa snazim problem vyriesit, no bezuspesne...
Stale potrebujem nacitat najvyssiu hodnotu (max) a nasledne ju navysenu o 1 zapisat (insert).
Na testovanie som spravil nasledujuci kod, na pracu s DB vyuzivam http://medoo.in
DB som dal InnoDB.
no a zial mi to vytvara cca 20 z 2000 zaznamov duplicitnych
//autoeditácia príspevku (28 Jún 2015, 22:48)
Uzamknutie tabulky ide, ale radsej by som skusil transakcie (kvoli rychlosti).
Stale sa snazim problem vyriesit, no bezuspesne...
Stale potrebujem nacitat najvyssiu hodnotu (max) a nasledne ju navysenu o 1 zapisat (insert).
Na testovanie som spravil nasledujuci kod, na pracu s DB vyuzivam http://medoo.in
DB som dal InnoDB.
Kód: Vybrať všetko
$db->query('SET SESSION TRANSACTION ISOLATION LEVEL 4;');
for ($i = 1; $i <= 1000; $i++) {
$db->pdo->beginTransaction();
$max = $db->max('test', 'value'); // SELECT MAX("value") FROM "test"
$last = $db->insert('test', [
'value' => ++$max,
'type' => $type // hodnota 1 alebo 2 na rozlisenie session
]); // INSERT INTO "test" ("value", "type") VALUES ('...', '...')
$db->pdo->commit();
}//autoeditácia príspevku (28 Jún 2015, 22:48)
Uzamknutie tabulky ide, ale radsej by som skusil transakcie (kvoli rychlosti).
Kód: Vybrať všetko
$db->query('LOCK TABLES test WRITE');-
harrison314
Hardcore addict
- Príspevky: 8217
- Registrovaný: 27 máj 2009, 20:42
- Bydlisko: Bratislava
- Kontaktovať používateľa:
Re: PHP, MySQL ochrana paralelne spustenych skriptov
Problem tvojho navrhu je ten, ze vytiahnes hodnotu, mimo Db inkrementujes a ulozis. na tvojom mieste by som sa zbavil inkrementovania mimo DB.
Radcej napis, co tym celim chces dosiahnut.
Radcej napis, co tym celim chces dosiahnut.
Re: PHP, MySQL ochrana paralelne spustenych skriptov
Okej, mam v db fotogalerie, fotky patriace do rovnakeho albumu maju rovnake "album_id" a kazdy album ma zoraditelne fotky, preto este ma kazda fotka aj "sort" hodnotu.
Preto ak pridavam novu fotku, musim zistit max(sort) pre dany album (album_id) a jej navysenu hodnotu zapisat ako novy zaznam spolu s album_id (a dalsimi hodnotami).
Autoincrement sa neda pouzit, kedze mam viac albumov a tym padom aj viac "sort" sekvenci 1 az x, kde x je pocet fotiek v danom albume.
Preto ak pridavam novu fotku, musim zistit max(sort) pre dany album (album_id) a jej navysenu hodnotu zapisat ako novy zaznam spolu s album_id (a dalsimi hodnotami).
Autoincrement sa neda pouzit, kedze mam viac albumov a tym padom aj viac "sort" sekvenci 1 az x, kde x je pocet fotiek v danom albume.
-
harrison314
Hardcore addict
- Príspevky: 8217
- Registrovaný: 27 máj 2009, 20:42
- Bydlisko: Bratislava
- Kontaktovať používateľa:
Re: PHP, MySQL ochrana paralelne spustenych skriptov
To je nieco ine ako som si myslel doteraz.
Pouzi trasnakciu len na selektnutie, inkrementaciu a ulozenie nic ine tam nedavaj (najme nie dlhotravjuci presun obrazku.
Alebo este lepsie sprav si na to stured proceduru.
Pouzi trasnakciu len na selektnutie, inkrementaciu a ulozenie nic ine tam nedavaj (najme nie dlhotravjuci presun obrazku.
Alebo este lepsie sprav si na to stured proceduru.
-
*****HERO*****
Guru wannabe
- Príspevky: 2446
- Registrovaný: 08 máj 2006, 1:34
Re: PHP, MySQL ochrana paralelne spustenych skriptov
a co takto?
+ na album_id hodit index, ked uz tam je ta subquerina
Kód: Vybrať všetko
INSERT INTO fotogaleria(album_id, sort, obrazok) VALUES(37, (SELECT MAX(sort) FROM fotogaleria WHERE album_id = 37) + 1, '/www/img/obrazok.jpg')-
harrison314
Hardcore addict
- Príspevky: 8217
- Registrovaný: 27 máj 2009, 20:42
- Bydlisko: Bratislava
- Kontaktovať používateľa:
Re: PHP, MySQL ochrana paralelne spustenych skriptov
Ok, beriem spet. Pouzi riesnie od HERO-a.
Re: PHP, MySQL ochrana paralelne spustenych skriptov
taketo riesenia som uz videl, no nie su to stale 2 query, ktore maju iba kratsi zapis ?*****HERO***** napísal:a co takto?
+ na album_id hodit index, ked uz tam je ta subquerinaKód: Vybrať všetko
INSERT INTO fotogaleria(album_id, sort, obrazok) VALUES(37, (SELECT MAX(sort) FROM fotogaleria WHERE album_id = 37) + 1, '/www/img/obrazok.jpg')
-
*****HERO*****
Guru wannabe
- Príspevky: 2446
- Registrovaný: 08 máj 2006, 1:34
Re: PHP, MySQL ochrana paralelne spustenych skriptov
ved ten insert ti zalockuje na write celu tabku, ak to je MyISAM, dokym sa nevykona aj s tym sub selectom, takze v pohode
Re: PHP, MySQL ochrana paralelne spustenych skriptov
toto funguje iba na MyISAM? mam teda ist do MyISAM namiesto InnoDB (tu som chcel kvoli transakciam)*****HERO***** napísal:ved ten insert ti zalockuje na write celu tabku, ak to je MyISAM, dokym sa nevykona aj s tym sub selectom, takze v pohode
a fakt diky chalani
Re: PHP, MySQL ochrana paralelne spustenych skriptov
to bude urcite safe aj v innodb
Re: PHP, MySQL ochrana paralelne spustenych skriptov
okej, ale tymto stylom nepomozem pouzit DB framework medoo, cize aj tak je to naj riesenie?
-
Fabo
Hardcore addict
- Príspevky: 6810
- Registrovaný: 16 nov 2007, 17:23
- Bydlisko: 's Chravenhache
- Kontaktovať používateľa:
Re: PHP, MySQL ochrana paralelne spustenych skriptov
mozes si aj v InnoDB nastavit table level locking (IIRC)
-
audiotrack
VIP
- Príspevky: 25958
- Registrovaný: 09 sep 2005, 18:39
- Kontaktovať používateľa:
Re: PHP, MySQL ochrana paralelne spustenych skriptov
ako presne vyzerá tá tabuľka? Daj sem jej export.
Na 99% to subquery nepotrebuješ. Ja by som dal tomu sortu autoincrement, a spolu s album_id ho dal do unique indexu (v jednom albume nemôžu byť dve fotky s rovnakým poradím). Ten unique je tam potrebný aby sa dal použiť autoincrement. A je po probléme. Pri vkladaní sa poradie rieši samé (je úplne jedno či fotky budú mať poradie 1,2,3.. alebo 3524, 4553, 5012.. stále budú vrámci albumu zoradené rovnako, lineárna usporiadanosť prirodzených čísel predsa funguje na celom definičnom obore). Pri update (zmene poradia), si tam už dáš číslovanie 1..x. Zase tu pomôže unique klúč s album_id aby neboli konflikty že viac fotiek má poradie 1 a pod.
čiže query od HERA by vyzeralopričom ten názov obrázku by nemal byť s cestou (zmeníš štruktúru pri migrovaní systému, a všetky obrázky ti zmiznú) ale tá by sa mala vyskladávať v aplikácii, a asi by som tam vôbec názov nedával. To by mala byť samostatná tabuľka obrázkov, kde bude názov, počet zobrazení, typ súboru a podobne, a do tejto fotogalerie dávať iba ID toho obrázku
Na 99% to subquery nepotrebuješ. Ja by som dal tomu sortu autoincrement, a spolu s album_id ho dal do unique indexu (v jednom albume nemôžu byť dve fotky s rovnakým poradím). Ten unique je tam potrebný aby sa dal použiť autoincrement. A je po probléme. Pri vkladaní sa poradie rieši samé (je úplne jedno či fotky budú mať poradie 1,2,3.. alebo 3524, 4553, 5012.. stále budú vrámci albumu zoradené rovnako, lineárna usporiadanosť prirodzených čísel predsa funguje na celom definičnom obore). Pri update (zmene poradia), si tam už dáš číslovanie 1..x. Zase tu pomôže unique klúč s album_id aby neboli konflikty že viac fotiek má poradie 1 a pod.
čiže query od HERA by vyzeralo
Kód: Vybrať všetko
INSERT INTO fotogaleria(album_id, obrazok) VALUES(37, 'obrazok.jpg')Re: PHP, MySQL ochrana paralelne spustenych skriptov
tabulka je taka, aku som popisal, nespomenul som iba ID, co je primary key
Dakujem, toto cele dava zmysel, otazne potom ostava, ako vyriesit komplet reorder jednou query.
Chcel by som tam mat drag&drop na zmenu poradia, ktore mi ako output da array s IDckami obrazkov.
Mam zobrazene napr. obrazky s ID 1, 2, 3, 4 - popresuvam ich a dostanem array [3,4,1,2] - a na tychto ID treba updatetnut hodnoty poradia, cize ID 3 bude mat sort 1, ID 4 bude mat sort 2 atd.
//autoeditácia príspevku (29 Jún 2015, 13:08)
preco aj unique je dolezity pri AI? hodnotu mi to pri zapise navysi aj bez unique, nie?audiotrack napísal:Ten unique je tam potrebný aby sa dal použiť autoincrement.
Dakujem, toto cele dava zmysel, otazne potom ostava, ako vyriesit komplet reorder jednou query.
Chcel by som tam mat drag&drop na zmenu poradia, ktore mi ako output da array s IDckami obrazkov.
Mam zobrazene napr. obrazky s ID 1, 2, 3, 4 - popresuvam ich a dostanem array [3,4,1,2] - a na tychto ID treba updatetnut hodnoty poradia, cize ID 3 bude mat sort 1, ID 4 bude mat sort 2 atd.
//autoeditácia príspevku (29 Jún 2015, 13:08)
to netreba teraz riesit, do DB zapisujem minimum (cize maximalne nazov bez cesty), cize potrebujem iba DB ochranit pred race conditionaudiotrack napísal:pričom ten názov obrázku by nemal byť s cestou