PHP, MySQL ochrana paralelne spustenych skriptov

Programovacie jazyky, rady, poradňa...
Boccaccio
Medium Professional
Medium Professional
Používateľov profilový obrázok
Príspevky: 1097
Registrovaný: 01 mar 2014, 14:00
Bydlisko: Bratislava

PHP, MySQL ochrana paralelne spustenych skriptov

Príspevok od používateľa Boccaccio »

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
harrison314
Hardcore addict
Hardcore addict
Používateľov profilový obrázok
Príspevky: 8216
Registrovaný: 27 máj 2009, 20:42
Bydlisko: Bratislava
Kontaktovať používateľa:

Re: PHP, MySQL ochrana paralelne spustenych skriptov

Príspevok od používateľa harrison314 »

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?
Nezanedbatelna.
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
Hardcore addict
Používateľov profilový obrázok
Príspevky: 6177
Registrovaný: 16 júl 2008, 20:29
Bydlisko: Pri PC
Kontaktovať používateľa:

Re: PHP, MySQL ochrana paralelne spustenych skriptov

Príspevok od používateľa Michaelo »

Na toto som sa pytal na StackExchange minule, kedze mi to vrtalo v hlave: http://programmers.stackexchange.com/qu ... -be-missed
Boccaccio
Medium Professional
Medium Professional
Používateľov profilový obrázok
Príspevky: 1097
Registrovaný: 01 mar 2014, 14:00
Bydlisko: Bratislava

Re: PHP, MySQL ochrana paralelne spustenych skriptov

Príspevok od používateľa Boccaccio »

Michaelo napísal:Na toto som sa pytal na StackExchange minule, kedze mi to vrtalo v hlave: http://programmers.stackexchange.com/qu ... -be-missed
Cize harrison sa myli vo svojej odpovedi?
audiotrack
VIP
VIP
Používateľov profilový obrázok
Príspevky: 25958
Registrovaný: 09 sep 2005, 18:39
Kontaktovať používateľa:

Re: PHP, MySQL ochrana paralelne spustenych skriptov

Príspevok od používateľa audiotrack »

á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
Hardcore addict
Používateľov profilový obrázok
Príspevky: 8216
Registrovaný: 27 máj 2009, 20:42
Bydlisko: Bratislava
Kontaktovať používateľa:

Re: PHP, MySQL ochrana paralelne spustenych skriptov

Príspevok od používateľa harrison314 »

audiotrack napísal:áno, mýli.
Nehovorim, ze moje rienie je nepristrelne. Ale riesnie od Boccaccia by som nikdy nepouzil, a viac informacii k tomu nedal.
Boccaccio
Medium Professional
Medium Professional
Používateľov profilový obrázok
Príspevky: 1097
Registrovaný: 01 mar 2014, 14:00
Bydlisko: Bratislava

Re: PHP, MySQL ochrana paralelne spustenych skriptov

Príspevok od používateľa Boccaccio »

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.

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();
}
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).

Kód: Vybrať všetko

$db->query('LOCK TABLES test WRITE');
harrison314
Hardcore addict
Hardcore addict
Používateľov profilový obrázok
Príspevky: 8216
Registrovaný: 27 máj 2009, 20:42
Bydlisko: Bratislava
Kontaktovať používateľa:

Re: PHP, MySQL ochrana paralelne spustenych skriptov

Príspevok od používateľa harrison314 »

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.
Boccaccio
Medium Professional
Medium Professional
Používateľov profilový obrázok
Príspevky: 1097
Registrovaný: 01 mar 2014, 14:00
Bydlisko: Bratislava

Re: PHP, MySQL ochrana paralelne spustenych skriptov

Príspevok od používateľa Boccaccio »

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.
harrison314
Hardcore addict
Hardcore addict
Používateľov profilový obrázok
Príspevky: 8216
Registrovaný: 27 máj 2009, 20:42
Bydlisko: Bratislava
Kontaktovať používateľa:

Re: PHP, MySQL ochrana paralelne spustenych skriptov

Príspevok od používateľa harrison314 »

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.
*****HERO*****
Guru wannabe
Guru wannabe
Používateľov profilový obrázok
Príspevky: 2446
Registrovaný: 08 máj 2006, 1:34

Re: PHP, MySQL ochrana paralelne spustenych skriptov

Príspevok od používateľa *****HERO***** »

a co takto?

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')
+ na album_id hodit index, ked uz tam je ta subquerina
harrison314
Hardcore addict
Hardcore addict
Používateľov profilový obrázok
Príspevky: 8216
Registrovaný: 27 máj 2009, 20:42
Bydlisko: Bratislava
Kontaktovať používateľa:

Re: PHP, MySQL ochrana paralelne spustenych skriptov

Príspevok od používateľa harrison314 »

Ok, beriem spet. Pouzi riesnie od HERO-a.
Boccaccio
Medium Professional
Medium Professional
Používateľov profilový obrázok
Príspevky: 1097
Registrovaný: 01 mar 2014, 14:00
Bydlisko: Bratislava

Re: PHP, MySQL ochrana paralelne spustenych skriptov

Príspevok od používateľa Boccaccio »

*****HERO***** napísal:a co takto?

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')
+ na album_id hodit index, ked uz tam je ta subquerina
taketo riesenia som uz videl, no nie su to stale 2 query, ktore maju iba kratsi zapis ?
*****HERO*****
Guru wannabe
Guru wannabe
Používateľov profilový obrázok
Príspevky: 2446
Registrovaný: 08 máj 2006, 1:34

Re: PHP, MySQL ochrana paralelne spustenych skriptov

Príspevok od používateľa *****HERO***** »

ved ten insert ti zalockuje na write celu tabku, ak to je MyISAM, dokym sa nevykona aj s tym sub selectom, takze v pohode
Boccaccio
Medium Professional
Medium Professional
Používateľov profilový obrázok
Príspevky: 1097
Registrovaný: 01 mar 2014, 14:00
Bydlisko: Bratislava

Re: PHP, MySQL ochrana paralelne spustenych skriptov

Príspevok od používateľa Boccaccio »

*****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
toto funguje iba na MyISAM? mam teda ist do MyISAM namiesto InnoDB (tu som chcel kvoli transakciam)

a fakt diky chalani 8)
ropman
Medium Professional
Medium Professional
Príspevky: 1250
Registrovaný: 12 apr 2010, 21:07

Re: PHP, MySQL ochrana paralelne spustenych skriptov

Príspevok od používateľa ropman »

to bude urcite safe aj v innodb
Boccaccio
Medium Professional
Medium Professional
Používateľov profilový obrázok
Príspevky: 1097
Registrovaný: 01 mar 2014, 14:00
Bydlisko: Bratislava

Re: PHP, MySQL ochrana paralelne spustenych skriptov

Príspevok od používateľa Boccaccio »

okej, ale tymto stylom nepomozem pouzit DB framework medoo, cize aj tak je to naj riesenie?
Fabo
Hardcore addict
Hardcore addict
Používateľov profilový obrázok
Príspevky: 6810
Registrovaný: 16 nov 2007, 17:23
Bydlisko: 's Chravenhache
Kontaktovať používateľa:

Re: PHP, MySQL ochrana paralelne spustenych skriptov

Príspevok od používateľa Fabo »

mozes si aj v InnoDB nastavit table level locking (IIRC)
audiotrack
VIP
VIP
Používateľov profilový obrázok
Príspevky: 25958
Registrovaný: 09 sep 2005, 18:39
Kontaktovať používateľa:

Re: PHP, MySQL ochrana paralelne spustenych skriptov

Príspevok od používateľa audiotrack »

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 vyzeralo

Kód: Vybrať všetko

INSERT INTO fotogaleria(album_id, obrazok) VALUES(37, 'obrazok.jpg')
prič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
Boccaccio
Medium Professional
Medium Professional
Používateľov profilový obrázok
Príspevky: 1097
Registrovaný: 01 mar 2014, 14:00
Bydlisko: Bratislava

Re: PHP, MySQL ochrana paralelne spustenych skriptov

Príspevok od používateľa Boccaccio »

tabulka je taka, aku som popisal, nespomenul som iba ID, co je primary key
audiotrack napísal:Ten unique je tam potrebný aby sa dal použiť autoincrement.
preco aj unique je dolezity pri AI? hodnotu mi to pri zapise navysi aj bez unique, nie?

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)
audiotrack napísal:pričom ten názov obrázku by nemal byť s cestou
to netreba teraz riesit, do DB zapisujem minimum (cize maximalne nazov bez cesty), cize potrebujem iba DB ochranit pred race condition
Napísať odpoveď