Stop concurrency in php
Ik wil echter dat een gedeelte van de code maar door één persoon tegelijkertijd kan worden uitgevoerd.
Ik heb al een halve oplossing bedacht, maar ik denk dat die het probleem niet echt zal oplossen:
Code (php)
1
2
3
4
5
6
7
8
9
10
11
2
3
4
5
6
7
8
9
10
11
<?php
//check SQL variabele
while (variable ==1)
{
wait(10);
//check SQL variabele
}
//set variabele op 1
//doe hier de "belangrijke code"
//set variabele op 0
?>
//check SQL variabele
while (variable ==1)
{
wait(10);
//check SQL variabele
}
//set variabele op 1
//doe hier de "belangrijke code"
//set variabele op 0
?>
maargoed bovenstaande code levert nog steeds dezelfde problemen op als twee personen op hetzelfde moment de SQL variabele checken en dan tegelijkertijd uit de while loop raken.
Zit er in PHP iets om dit op een natuurlijke manier af te dwingen?
Gewijzigd op 11/08/2011 12:34:55 door Anorionil Black
Maar.... wat betreft jouw vraag. Waarom zou je dat willen?
Uhm ja maar in een groter systeem (bijvoorbeeld een spel) waarbij al die gegevens wel worden opgeslagen zou het wel mogelijk zijn. Maar het probleem zou er nog steeds zijn met een timestamp in de database aangezien je niet de check en de aanpassing in één query kan doen, of wel?
Persoon 1 voert query A uit. Als dit gebeurd is, wordt er een tijdstempel in de database opgeslagen.
Persoon 2 wil query A ook uitvoeren. De tijdstempel wordt opgehaald. Is de huidige tijd 10 seconden later dat de tijdstempel dan mag query A worden uitgevoerd. Is dit niet het geval dan mag query A niet worden uitgevoerd.
Is dat wat je bedoelt?
Als het probleem in een query/update zit, kun je het waarschijnlijk ook daar oplossen.
transactions en InnoDB wel zoiets bereiken op database niveau. Dat zorgt er in ieder geval voor dat binnen die transactie de waarden in de database niet tussentijds veranderen. Ik weet niet of je ook een lock op een tabel kan verkrijgen zodat anderen niet tegelijkertijd kunnen lezen.
Volgens mij kan je met Dat kan met Doctrine wel, alleen is misschien wat hoog gegrepen :)
… maar ik kan in hun dbal documentatie niets vinden over locks, alleen over transactions. En die beschermen je alleen tegen dubbel schrijven. Volgens mij heb je een table lock nodig als je ook het lezen tijdens je bewerkingen wilt blokkeren.
Bedankt voor alle reacties tot nu toe. Ik zal het probleem nog iets verder toelichten:
Het gaat om een spel dat o.a. door middel van PHP wordt gespeeld. Er zitten verschillende spelers in een potje. In principe komt elke speler om de beurt aan de beurt, maar in sommige gevallen kunnen verschillende mensen tegelijkertijd knoppen gebruiken. Zo'n knop stuurt een bericht naar een php script dat dan wordt uitgevoerd. In sommige gevallen mag het echter niet zo zijn dat het script dubbel wordt aangeroepen, oftewel, dat tijdens de uitvoer door een request van één persoon hij nog een keer begint uit te voeren voor een ander persoon.
Een Table Lock gaat het denk ik niet oplossen, omdat er verschillende potjes tegelijkertijd gespeeld kunnen worden, en ik kan niet voor elk potje een table aanmaken. Ik zou eerder een "Row Lock" willen hebben zeg maar.
Voor zover ik de uitleg bij Transactions begrijp, is dit ook niet de oplossing die ik zoek.
Zou het niet mogelijk zijn om ín de query een IF te zetten. Als het ware de query: "UPDATE * FROM blabla IF test=0 ELSE return null" ofzo? Of kan ik misschien achteraf checken of een bepaalde update ook heeft plaatsgevonden door een specefieke query?
Jelmer rrrr op 11/08/2011 23:07:55:
Niet interessant dat Doctrine het kan, maar interessant hoe ze het doen! :D
… maar ik kan in hun dbal documentatie niets vinden over locks, alleen over transactions. En die beschermen je alleen tegen dubbel schrijven. Volgens mij heb je een table lock nodig als je ook het lezen tijdens je bewerkingen wilt blokkeren.
… maar ik kan in hun dbal documentatie niets vinden over locks, alleen over transactions. En die beschermen je alleen tegen dubbel schrijven. Volgens mij heb je een table lock nodig als je ook het lezen tijdens je bewerkingen wilt blokkeren.
Het zit in hun ORM laag van versie 2.x. Bij het opvragen van een entity uit de EntityManager kun je een lock type constante meegeven :)
http://www.doctrine-project.org/docs/orm/2.0/en/reference/transactions-and-concurrency.html
Gewijzigd op 17/08/2011 19:09:00 door kees Schepers